C#のWPFで色選択コントロールを自作する その2

前回に続いて、色を選択するコントロールを作成してみる

 

まずはXAMLの中身から。

XAML

<UserControl x:Class="WpfApplication1.ColorPicker"
             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:WpfApplication1"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <Style x:Key="ColorPickerStyle" TargetType="ComboBox">
            <Style.Triggers>
                <Trigger Property="IsEditable" Value="False">
                    <Setter Property="Background" Value="White"/>
                </Trigger>
            </Style.Triggers>
            <Setter Property="BorderBrush" Value="LightGray"/>
            <Setter Property="Background" Value="White"/>
            <Setter Property="ToggleButton.Background" Value="White"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="VerticalContentAlignment" Value="Stretch"/>
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <Grid Margin="0,0,5,0">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="0"/>
                            </Grid.RowDefinitions>
                        </Grid>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="ItemContainerStyle">
                <Setter.Value>
                    <Style TargetType="{x:Type ComboBoxItem}">
                        <Setter Property="Grid.Column" Value="{Binding Column}"/>
                        <Setter Property="Grid.Row" Value="{Binding Row}"/>
                        <Setter Property="Margin" Value="0"/>
                        <Setter Property="Padding" Value="1"/>
                    </Style>
                </Setter.Value>
            </Setter>
            <Setter Property="ItemTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <Border Margin="0" MinWidth="14" MinHeight="14"
                            HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                            BorderThickness="1" BorderBrush="Gray"
                            Background="{Binding ItemBrush}"
                            ToolTip="{Binding ToolTip}"/>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <DataTemplate x:Key="ColorPickerHeaderTemplate1">
            <Border Margin="0,5,0,0"/>
        </DataTemplate>
        <DataTemplate x:Key="ColorPickerHeaderTemplate2">
            <TextBlock Margin="5" TextAlignment="Right"><Hyperlink Click="Hyperlink_Click">その他の色...</Hyperlink></TextBlock>
        </DataTemplate>
        <local:ColorPickerHeaderTemplateSelector x:Key="ColorPickerHeaderSelector"
                                Template1="{StaticResource ColorPickerHeaderTemplate1}"
                                Template2="{StaticResource ColorPickerHeaderTemplate2}"/>
    </UserControl.Resources>
    <ComboBox Name="Main" Style="{StaticResource ColorPickerStyle}" SelectionChanged="Main_SelectionChanged">
        <ComboBox.GroupStyle>
            <GroupStyle HeaderTemplateSelector="{StaticResource ColorPickerHeaderSelector}"/>
        </ComboBox.GroupStyle>
    </ComboBox>
</UserControl>

ItemsPanelのカスタマイズ (21~54行目)

色をタイル状に並べる為にGridコントロールを使っている。

※GroupStyleを使ってグループ毎に表示する為RowDefinitionは10個もいらないけど分かりやすくこうした

 

RowDefinitionの最後だけHeightに0を指定している。(49行目)

これは「その他の色...」から作成したカスタム色のアイテムを入れる為で、見えないようにしている

 

 

ItemContainerStyleのカスタマイズ (55~64行目)

Grid.ColumnとGrid.Rowをそれぞれバインディングするデータソースからセットさせる。

また、マウスオーバー時の選択色が見えるようにPaddingに1を指定している。

 

 

ItemTemplateのカスタマイズ (65~75行目)

Borderコントロールを使って四角を表示させている。

サイズはMinWidthとMinHeightを使って指定。

GridのRow,ColumnはサイズをAutoにしているのでプルダウンで表示される時は最小サイズの四角で並べられる。でComboBoxのメインの部分はContentAlignmentをStretch(19~20行目)にしているのでサイズいっぱいに引き伸ばされて表示される。

※ComboCoxが四角の最小サイズより小さい場合の事は考えない事にする

 

 

グループヘッダーのカスタマイズ (77~85行目)

2つのグループヘッダー用テンプレートを用意。

ColorPickerHeaderTemplate1はスペースを開けたい為だけのヘッダー。

ColorPickerHeaderTemplate2はカスタム色用のハイパーリンクを設けたヘッダー。

ColorPickerHeaderTemplateSelectorでカスタム用グループのみTemplate2を使うように制御する。

  

つづく