VB のたまご

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



ControlTemplate

  •  ControlTemplate は、コントロールの見た目を独自にカスタマイズできる仕組みです。 とりあえずどういう風に動くのか見てみましょう。 以下サンプルです。「ControlTemplateWindow1」という画面で作成していますが、「MainWindow」に書いても構いません。

  • スポンサーリンク


    <Window x:Class="ControlTemplateWindow1"
            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:w05_WpfSystem"
            mc:Ignorable="d"
            Title="ControlTemplateWindow1" Height="300" Width="300">
    
        <StackPanel>
    
            <Button Content="button1" Margin="10" Click="Button_Click">
                <Button.Template>
                    <ControlTemplate TargetType="Button">
                        <Border BorderBrush="Olive" BorderThickness="1" CornerRadius="1" Background="White">
                            <StackPanel Orientation="Horizontal">
                                <Rectangle Fill="Olive" Width="16" Height="16" />
                                <ContentPresenter VerticalAlignment="Center" />
                            </StackPanel>
                        </Border>
                    </ControlTemplate>
                </Button.Template>
            </Button>
            
        </StackPanel>
        
    </Window>
    

    Public Class ControlTemplateWindow1
    
        Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    
            MessageBox.Show("Hello, WPF!")
    
        End Sub
    
    End Class
    

  •  ボタンの見た目を四角形と表示文字列で構成される形にカスタマイズしたサンプルです。 ControlTemplate は、Button の Template プロパティに設定します。 Style と同じで、対象コントロールを指定して使います。

  •  ContentPresenter というのは、指定コントロール(ここでは Button) の Content プロパティの事です。 Button タグの Content プロパティに button1 をセットしていますがこの文字列が、ここの位置に表示されるように配置しました。 Border の Background に White をわざわざ設定したのは、これをセットしないとクリックが反応しないためです。

  •  もちろん ControlTemplate もリソースに定義することができます。次のサンプルです。

  • <Window x:Class="ControlTemplateWindow2"
            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:w05_WpfSystem"
            mc:Ignorable="d"
            Title="ControlTemplateWindow2" Height="300" Width="300">
    
        <StackPanel>
    
            <StackPanel.Resources>
                
                <ControlTemplate x:Key="ButtonTemplate" TargetType="Button">
                    <Border BorderBrush="Olive" BorderThickness="1" CornerRadius="1" Background="White">
                        <StackPanel Orientation="Horizontal">
                            <Rectangle Fill="Olive" Width="16" Height="16" />
                            <ContentPresenter VerticalAlignment="Center" />
                        </StackPanel>
                    </Border>
                </ControlTemplate>
                
            </StackPanel.Resources>
    
            <Button Content="button1" Margin="10" Click="Button_Click" 
                    Template="{StaticResource ButtonTemplate}" />
    
        </StackPanel>
    
    </Window>
    

    Public Class ControlTemplateWindow2
    
        Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    
            MessageBox.Show("Hello, WPF!")
    
        End Sub
    
    End Class
    

  •  リソースとして定義するためには、キー名ありで定義しないとエラーになってしまいます。 Style の設定の一部として ControlTemplate を含めることもできます。この場合は強制適用することができます。

  • <Window x:Class="ControlTemplateWindow3"
            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:w05_WpfSystem"
            mc:Ignorable="d"
            Title="ControlTemplateWindow3" Height="300" Width="300">
    
        <StackPanel>
    
            <StackPanel.Resources>
    
                <Style TargetType="Button">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="Button">
                                <Border BorderBrush="Blue" BorderThickness="1" CornerRadius="1" Background="White">
                                    <StackPanel Orientation="Horizontal">
                                        <Rectangle Fill="Blue" Width="16" Height="16" />
                                        <ContentPresenter VerticalAlignment="Center" />
                                    </StackPanel>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
                
                <ControlTemplate x:Key="ButtonTemplate" TargetType="Button">
                    <Border BorderBrush="Olive" BorderThickness="1" CornerRadius="1" Background="White">
                        <StackPanel Orientation="Horizontal">
                            <Rectangle Fill="Olive" Width="16" Height="16" />
                            <ContentPresenter VerticalAlignment="Center" />
                        </StackPanel>
                    </Border>
                </ControlTemplate>
    
            </StackPanel.Resources>
    
            <Button Content="button1" Margin="10" Click="Button_Click" />
    
            <Button Content="button2" Margin="10" Click="Button_Click" 
                    Template="{StaticResource ButtonTemplate}" />
    
        </StackPanel>
    
    </Window>
    

    Public Class ControlTemplateWindow3
    
        Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    
            MessageBox.Show("Hello, WPF!")
    
        End Sub
    
    End Class
    

  •  1つ目のボタンがスタイルに含めた ControlTemplate を適用させたボタンで、2つ目のボタンが独立して定義した ControlTemplate を適用させたボタンです。

  • スポンサーリンク


  •  続いて、以下は表示専門系コントロールのクリックイベントについてのサンプルです。 TextBlock や Label には Click イベントがありません。 個人的には MouseUp や KeyUp などで代替していいんじゃないかと思いましたが、サンプルということで。

  •  ここでのポイントは、やはり ControlTemplate で、ボタンコントロールの作り方に注目です。

  • <Window x:Class="ControlTemplateWindow4"
            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:w05_WpfSystem"
            mc:Ignorable="d"
            Title="ControlTemplateWindow4" Height="300" Width="300">
       
        <StackPanel>
    
            <TextBlock Text="textblock1" MouseUp="TextBlock_MouseUp" />
            <Label Content="label1" MouseUp="Label_MouseUp" />
    
            <Button Content="button1" Click="Button_Click">
                <Button.Template>
                    <ControlTemplate TargetType="Button">
                        <Label Content="{TemplateBinding Content}" />
                    </ControlTemplate>
                </Button.Template>
            </Button>
            
            <Button Content="button2" Click="Button_Click">
                <Button.Template>
                    <ControlTemplate TargetType="Button">
                        <ContentPresenter />
                    </ControlTemplate>
                </Button.Template>
            </Button>
    
            <Button Content="button3" Click="Button_Click">
                <Button.Template>
                    <ControlTemplate TargetType="Button">
                        <TextBlock Text="{TemplateBinding Content}" />
                    </ControlTemplate>
                </Button.Template>
            </Button>
    
            <TextBlock Text="textblock2" MouseUp="TextBlock_MouseUp" />
            
        </StackPanel>
        
    </Window>
    

    Public Class ControlTemplateWindow4
    
        Private Sub TextBlock_MouseUp(sender As Object, e As MouseButtonEventArgs)
    
            Console.WriteLine("TextBlock_MouseUp")
    
        End Sub
    
        Private Sub Label_MouseUp(sender As Object, e As MouseButtonEventArgs)
    
            Console.WriteLine("Label_MouseUp")
    
        End Sub
    
        Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    
            Console.WriteLine("Button_Click")
    
        End Sub
    
    End Class
    

  •  ControlTemplate に Label や TextBlock を配置することで、見た目を Label や TextBlock に変更することができます。 ControlTemplate に Label を配置すると、マージンが含まれるようですね。 ControlTemplate に ContentPresenter をセットするか、TextBlock をセットすることでマージン無しで表示できるようになります。

  •  TemplateBinding は、対象コントロールの指定プロパティをそのままセットするための命令です。 例えば、1つ目のボタンの ControlTemplate に Label をセットしていますが、Label 内の Content プロパティには、Button でセットした Content (=button1)をセットするように命令しています。