VB のたまご

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



カスタムコントロール

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

  • スポンサーリンク


  •  丸い枠のボタンを作ります。 「プロジェクト」→「新しい項目の追加」で、一覧から「カスタムコントロール(WPF)」を選択して、カスタムコントロールを作成します。

  •  カスタムコントロールは、Themes/Generic.xaml に、コントロールのデザイン設計(スタイルによる ControlTemplate 設計)をして、 内部設計は、ソースに定義します。

  •  カスタムコントロールの Xaml デザインを以下のように設計します。

  • <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:w08_YourControls2">
    
        <Style TargetType="{x:Type local:CircleButton}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:CircleButton}">
                        <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
    
                            <Grid>
    
                                <Ellipse Stroke="Olive" Width="32" Height="32" />
                                <TextBlock Text="{Binding Path=Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:CircleButton}}}" HorizontalAlignment="Center" VerticalAlignment="Center" />
    
                            </Grid>
    
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
    

  •  新しい指定の命令が出てきましたね。FindAncestor は親をめぐってルートの先祖コントロールまでさかのぼって、指定コントロールを探す指示となります。 以下は、自分の先祖をめぐって、CircleButton クラスを探す事、そのクラスメンバーの Text プロパティをバインドしたい、という意味です。 Binding Path=Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:CircleButton}}}

  • スポンサーリンク


  •  それでは内部処理を作っていきましょう。CircleButton.vb にコンストラクタ以降の処理を追加していきます。

  • ' このカスタム コントロールを XAML ファイルで使用するには、手順 1a または 1b の後、手順 2 に従います。
    '
    ' 手順 1a) 現在のプロジェクトに存在する XAML ファイルでこのカスタム コントロールを使用する場合
    ' この XmlNamespace 属性を使用場所であるマークアップ ファイルのルート要素に
    ' 追加します:
    '
    '     xmlns:MyNamespace="clr-namespace:w08_YourControls2"
    '
    '
    ' 手順 1b) 異なるプロジェクトに存在する XAML ファイルでこのカスタム コントロールを使用する場合
    ' この XmlNamespace 属性を使用場所であるマークアップ ファイルのルート要素に
    ' 追加します:
    '
    '     xmlns:MyNamespace="clr-namespace:w08_YourControls2;assembly=w08_YourControls2"
    '
    ' また、XAML ファイルのあるプロジェクトからこのプロジェクトへのプロジェクト参照を追加し、
    ' リビルドして、コンパイル エラーを防ぐ必要があります:
    '
    '     ソリューション エクスプローラーで対象のプロジェクトを右クリックし、
    '     [参照の追加] の [プロジェクト] を選択してから、このプロジェクトを参照し、選択します。
    '
    '
    ' 手順 2)
    ' コントロールを XAML ファイルで使用します。XML エディターの Intellisense が
    ' カスタム コントロールとその子要素に対して現在機能しないことに注意してください。
    '
    '     <MyNamespace:CircleButton/>
    '
    
    Imports System.Windows.Controls.Primitives
    
    
    Public Class CircleButton
        Inherits System.Windows.Controls.Control
    
        Shared Sub New()
            'この OverrideMetadata 呼び出しは、この要素が基底クラスと異なるスタイルを提供することをシステムに通知します。
            'このスタイルは themes\generic.xaml に定義されています
            DefaultStyleKeyProperty.OverrideMetadata(GetType(CircleButton), New FrameworkPropertyMetadata(GetType(CircleButton)))
        End Sub
    
        ' 独自ボタンに表示する文字列テキストプロパティ
        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
    
        Public Overrides Sub OnApplyTemplate()
            MyBase.OnApplyTemplate()
        End Sub
    
    End Class
    

  •  これで、カスタムコントロールの作成が完了しました。それでは自作コントロールを使ってみます。

  • <Window x:Class="CustomControlWindow1"
            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:w08_YourControls2"
            mc:Ignorable="d"
            Title="CustomControlWindow1" 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 CustomControlWindow1
    
        Private Sub CircleButton_Click(sender As Object, e As RoutedEventArgs)
    
            Console.WriteLine("Hello, WPF!")
    
        End Sub
    
    End Class
    

  •  このサンプルは UserControl の説明に書いた、1つ目の自作コントロールと同じものです。 UserControl と CustomControl の違いや使い分けについては、申し訳ないですが私もよく分かっていません。 今できることは、どちらの方法でも作れるように作り方を覚えるしかないかなと思っています。