VB のたまご

作成日: 2017/03/07, 更新日: 2017/03/07



ユーザーコントロール

  •  UserControl は、独自コントロールを扱いたい時に作成するコントロールです。 とりあえず作ってみましょう。

  • スポンサーリンク


  •  丸い枠のボタンを作ります。 「プロジェクト」→「ユーザーコントロールの作成」で、一覧から「ユーザーコントロール(WPF)」を選択して、ユーザーコントロールの Xaml デザインを以下のように設計します。

  • <UserControl x:Class="CircleButton"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:w07_YourControls"
                 mc:Ignorable="d" 
                 Name="root"
                 d:DesignHeight="300" d:DesignWidth="300">
    
        <Grid>
            
            <Ellipse Stroke="Olive" Width="32" Height="32" />
            <TextBlock Text="{Binding Path=Text, ElementName=root}" HorizontalAlignment="Center" VerticalAlignment="Center" />
       
        </Grid>
        
    </UserControl>
    

  •  表示する文字列プロパティと独自ボタンのクリックイベントを定義します。

  • Public Class CircleButton
    
        ' 独自ボタンに表示する文字列テキストプロパティ
        Public Shared ReadOnly TextProperty As DependencyProperty = DependencyProperty.Register(
            "Text",
            GetType(String),
            GetType(CircleButton),
            New PropertyMetadata("実行"))
    
        Public Property Text As String
            Get
                Return CStr(GetValue(TextProperty))
            End Get
            Set(value As String)
                SetValue(TextProperty, value)
            End Set
        End Property
    
        ' 独自ボタンのクリックイベント
        Public Shared ReadOnly ClickEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
            "Click",
            RoutingStrategy.Bubble,
            GetType(RoutedEventHandler),
            GetType(CircleButton))
    
        Public Custom Event Click As RoutedEventHandler
            AddHandler(value As RoutedEventHandler)
                Me.AddHandler(ClickEvent, value)
            End AddHandler
            RemoveHandler(value As RoutedEventHandler)
                Me.RemoveHandler(ClickEvent, value)
            End RemoveHandler
            RaiseEvent(sender As Object, e As RoutedEventArgs)
                Me.RaiseEvent(e)
            End RaiseEvent
        End Event
    
        Protected Overrides Sub OnMouseLeftButtonUp(e As MouseButtonEventArgs)
            MyBase.OnMouseLeftButtonUp(e)
            Me.RaiseEvent(New RoutedEventArgs(ClickEvent))
        End Sub
    
    End Class
    

  •  以上で、ユーザーコントロールが完成しました。それではこのコントロールを使ってみます。 一回ビルドすると?、ツールボックスに CircleButton が表示されると思うので、ドラッグアンドドロップしてもいいですし、 直接タグ入力してもいいので、以下のように記述します。

  • <Window x:Class="UserControlWindow1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:w07_YourControls"
            mc:Ignorable="d"
            Title="UserControlWindow1" Height="300" Width="300">
    
        <StackPanel Margin="10">
    
            <local:CircleButton Click="CircleButton_Click" />
            <local:CircleButton Text="開始" Click="CircleButton_Click" />
            
            <local:CircleButton Click="CircleButton_Click">
                <local:CircleButton.Template>
                    <ControlTemplate TargetType="{x:Type local:CircleButton}">
                        <Grid>
                            <Rectangle Stroke="Olive" Width="32" Height="32" />
                            <TextBlock Text="実行" HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Grid>
                    </ControlTemplate>
                </local:CircleButton.Template>
            </local:CircleButton>
            
        </StackPanel>
    
    </Window>
    

    Public Class UserControlWindow1
    
        Private Sub CircleButton_Click(sender As Object, e As RoutedEventArgs)
    
            Console.WriteLine("MainWindow 側からのメッセージ")
    
        End Sub
    
    End Class
    

  •  何も設定しない場合は「実行」という初期値の文字列が、Text プロパティに設定した場合はその値がボタンの中に表示されました。 また、クリックすることでイベント発生したことが分かると思います。

  • スポンサーリンク


  •  2つ目は、RGBと透明度の設定を確認できるプレビューコントロールを作ります。

  • <UserControl x:Class="ColorPreviewTextBox"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:w07_YourControls"
                 mc:Ignorable="d" 
                 Name="root"
                 d:DesignHeight="300" d:DesignWidth="300">
    
        <Grid>
    
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
    
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
    
            <!-- 色のプレビュー -->
            <Border BorderBrush="Silver" BorderThickness="1"
                    Grid.Row="0" Grid.Column="0" Grid.RowSpan="4">
                <Rectangle Name="rectangle1" />
            </Border>
    
            <!-- 赤 -->
            <Grid Grid.Row="0" Grid.Column="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
    
                <TextBlock 
                    Text="red:" 
                    VerticalAlignment="Center"
                    HorizontalAlignment="Right"
                    Grid.Column="0" />
    
                <TextBox 
                    Text="{Binding Path=RedText, ElementName=root, UpdateSourceTrigger=PropertyChanged}"
                    VerticalAlignment="Stretch" HorizontalAlignment="Stretch"  
                    VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
                    Grid.Column="1" />
    
            </Grid>
    
            <!-- 緑 -->
            <Grid Grid.Row="1" Grid.Column="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
    
                <TextBlock 
                    Text="green:" 
                    VerticalAlignment="Center"
                    HorizontalAlignment="Right"
                    Grid.Column="0" />
    
                <TextBox 
                    Text="{Binding Path=GreenText, ElementName=root, UpdateSourceTrigger=PropertyChanged}"
                    VerticalAlignment="Stretch" HorizontalAlignment="Stretch"  
                    VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
                    Grid.Column="1" />
    
            </Grid>
    
            <!-- 青 -->
            <Grid Grid.Row="2" Grid.Column="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
    
                <TextBlock 
                    Text="blue:" 
                    VerticalAlignment="Center"
                    HorizontalAlignment="Right"
                    Grid.Column="0" />
    
                <TextBox 
                    Text="{Binding Path=BlueText, ElementName=root, UpdateSourceTrigger=PropertyChanged}"
                    VerticalAlignment="Stretch" HorizontalAlignment="Stretch"  
                    VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
                    Grid.Column="1" />
    
            </Grid>
    
            <!-- アルファ値(透明度) -->
            <Grid Grid.Row="3" Grid.Column="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
    
                <TextBlock 
                    Text="transparent:" 
                    VerticalAlignment="Center"
                    HorizontalAlignment="Right"
                    Grid.Column="0" />
    
                <TextBox 
                    Text="{Binding Path=TransparentText, ElementName=root, UpdateSourceTrigger=PropertyChanged}"
                    VerticalAlignment="Stretch" HorizontalAlignment="Stretch"  
                    VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
                    Grid.Column="1" />
    
            </Grid>
    
        </Grid>
    
    </UserControl>
    

    Public Class ColorPreviewTextBox
    
        ' 赤のプロパティ
        Public Shared ReadOnly RedTextProperty As DependencyProperty = DependencyProperty.Register(
            "RedText",
            GetType(String),
            GetType(ColorPreviewTextBox),
            New PropertyMetadata("0", AddressOf PropertyChanged))
    
        Public Property RedText As String
            Get
                Return CStr(GetValue(RedTextProperty))
            End Get
            Set(value As String)
                SetValue(RedTextProperty, value)
            End Set
        End Property
    
        ' 緑のプロパティ
        Public Shared ReadOnly GreenTextProperty As DependencyProperty = DependencyProperty.Register(
            "GreenText",
            GetType(String),
            GetType(ColorPreviewTextBox),
            New PropertyMetadata("0", AddressOf PropertyChanged))
    
        Public Property GreenText As String
            Get
                Return CStr(GetValue(GreenTextProperty))
            End Get
            Set(value As String)
                SetValue(GreenTextProperty, value)
            End Set
        End Property
    
        ' 青のプロパティ
        Public Shared ReadOnly BlueTextProperty As DependencyProperty = DependencyProperty.Register(
            "BlueText",
            GetType(String),
            GetType(ColorPreviewTextBox),
            New PropertyMetadata("0", AddressOf PropertyChanged))
    
        Public Property BlueText As String
            Get
                Return CStr(GetValue(BlueTextProperty))
            End Get
            Set(value As String)
                SetValue(BlueTextProperty, value)
            End Set
        End Property
    
        ' 透明度のプロパティ
        Public Shared ReadOnly TransparentTextProperty As DependencyProperty = DependencyProperty.Register(
            "TransparentText",
            GetType(String),
            GetType(ColorPreviewTextBox),
            New PropertyMetadata("0", AddressOf PropertyChanged))
    
        Public Property TransparentText As String
            Get
                Return CStr(GetValue(TransparentTextProperty))
            End Get
            Set(value As String)
                SetValue(TransparentTextProperty, value)
            End Set
        End Property
    
        ' 各値のプロパティ変更時の処理
        Private Shared Sub PropertyChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
    
            Dim thisControl = TryCast(d, ColorPreviewTextBox)
            If thisControl Is Nothing Then
                Exit Sub
            End If
    
            ' Me.Xxx とアクセスできないが、引数経由で本画面のインスタンスを取得できる、これ経由で値の更新をかける
            Dim transparentValue = CInt(thisControl.TransparentText)
            Dim redValue = CInt(thisControl.RedText)
            Dim greenValue = CInt(thisControl.GreenText)
            Dim blueValue = CInt(thisControl.BlueText)
            thisControl.rectangle1.Fill = New SolidColorBrush(Color.FromArgb(
                                                              CByte(transparentValue),
                                                              CByte(redValue),
                                                              CByte(greenValue),
                                                              CByte(blueValue)))
    
        End Sub
    
    End Class
    

    <Window x:Class="UserControlWindow2"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:w07_YourControls"
            mc:Ignorable="d"
            Title="UserControlWindow2" Height="350" Width="400">
    
        <StackPanel Margin="10">
    
            <local:ColorPreviewTextBox 
                Margin="10"
                RedText="255"
                GreenText="0"
                BlueText="0"
                TransparentText="10" />
    
            <local:ColorPreviewTextBox 
                Margin="10"
                RedText="0"
                GreenText="255"
                BlueText="0"
                TransparentText="10" />
    
            <local:ColorPreviewTextBox 
                Margin="10"
                RedText="0"
                GreenText="0"
                BlueText="255"
                TransparentText="10" />
    
        </StackPanel>
    
    </Window>
    

    Public Class UserControlWindow2
    
    End Class
    

  •  ここでは、UpdateSourceTrigger という指示が初めて出てきました。 「Binding Path=RedText, ElementName=root, UpdateSourceTrigger=PropertyChanged」、これは、 「root」という名前のコントロールのメンバーである「RedText」プロパティをバインドして表示してほしい、 「RedText」プロパティの値は「Text」プロパティとバインドしているわけだが、更新タイミングを入力文字が変更されたとき、つまり TextChanged イベント的に更新するように動作します。

  •  0 ~ 255 までの「半角数値」を入力してみてください。色が変更されます。 ちなみに、数値以外、文字を入力しようとすると、以下のように例外エラーが発生してしまいますorz。

  • 型 'System.InvalidCastException' の例外が Microsoft.VisualBasic.dll で発生しましたが、ユーザー コード内ではハンドルされませんでした
    
    追加情報:String "a" から型 'Integer' への変換は無効です。