[ C# ] WPF TabControlのタブの色変更

タブコントロールのタブの背景色の変更が面倒だった

デフォルトでは、選択時は白色になります。

それを、選択時も同色にしたかった。

1.ControlTemplateの作成

ベースは自動で作成できるテンプレートを改造(それでちょっと長い)

<Window.Resources>
    <ControlTemplate x:Key="TabItemControlTemplate1" TargetType="{x:Type TabItem}">
        <Grid x:Name="templateRoot" SnapsToDevicePixels="True">
           <Border x:Name="mainBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0" Background="#FFFFCDCD" Margin="0">
               <Border x:Name="innerBorder" BorderBrush="#FFACACAC" BorderThickness="1,1,1,0" Background="#FFFFCDCD" Margin="-1" Opacity="0"/>
           </Border>
           <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" Focusable="False" HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
        </Grid>
        <ControlTemplate.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="false"/>
                    <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Top"/>
                </MultiDataTrigger.Conditions>
                <Setter Property="BorderThickness" TargetName="innerBorder" Value="1,1,1,0"/>
                <Setter Property="BorderThickness" TargetName="mainBorder" Value="1,1,1,0"/>
                <Setter Property="Background" TargetName="innerBorder" Value="#FFFFCDCD" />
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="true"/>
                    <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Top"/>
                </MultiDataTrigger.Conditions>
                <Setter Property="Panel.ZIndex" Value="1"/>
                <Setter Property="Margin" Value="-2,-2,-2,0"/>
                <Setter Property="Opacity" TargetName="innerBorder" Value="1"/>
            </MultiDataTrigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    <ControlTemplate x:Key="TabItemControlTemplate2" TargetType="{x:Type TabItem}">
        <Grid x:Name="templateRoot" SnapsToDevicePixels="True">
            <Border x:Name="mainBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0" Background="#FFCDFFCD" Margin="0">
                <Border x:Name="innerBorder" BorderBrush="#FFACACAC" BorderThickness="1,1,1,0" Background="#FFCDFFCD" Margin="-1" Opacity="0"/>
            </Border>
            <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" Focusable="False" HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
        </Grid>
        <ControlTemplate.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="false"/>
                    <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Top"/>
                </MultiDataTrigger.Conditions>
                <Setter Property="BorderThickness" TargetName="innerBorder" Value="1,1,1,0"/>
                <Setter Property="BorderThickness" TargetName="mainBorder" Value="1,1,1,0"/>
                <Setter Property="Background" TargetName="innerBorder" Value="#FFFFCDCD" />
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="true"/>
                    <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Top"/>
                </MultiDataTrigger.Conditions>
                <Setter Property="Panel.ZIndex" Value="1"/>
                <Setter Property="Margin" Value="-2,-2,-2,0"/>
                <Setter Property="Opacity" TargetName="innerBorder" Value="1"/>
            </MultiDataTrigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
</Window.Resources>

コードを見ると、Borderの背景色が表示されているようで、選択/非選択時にBorderが切り替わってる感じです。

Gridは描画の部分で、ここの数値を変えることで見た目が変わります。

MultiDataTriggerで、選択/非選択の描画を切り替えます。

トリガーでマウスオーバーとか追加すれば、各状態ごとに見た目が変えれます。

2.TabControlにテンプレートを適用

<TabControl HorizontalAlignment="Left" Height="131" Margin="31,21,0,0" VerticalAlignment="Top" Width="291">
    <TabItem Header="TabItem" Template="{DynamicResource TabItemControlTemplate1}">
        <Grid Background="#FFE5E5E5"/>
    </TabItem>
    <TabItem Header="TabItem" Template="{DynamicResource TabItemControlTemplate2}">
        <Grid Background="#FFE5E5E5"/>
    </TabItem>
    <TabItem Header="TabItem">
        <Grid Background="#FFE5E5E5"/>
    </TabItem>
</TabControl>

3.もっとシンプルに(ただのフラット)

<ControlTemplate x:Key="TabItemControlTemplate1" TargetType="{x:Type TabItem}">
    <Grid x:Name="templateRoot" SnapsToDevicePixels="True" Margin="0,0,8,0" Width="50">
        <Border x:Name="mainBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0" Background="#FFFFCDCD" Margin="-2,-2,-2,-1">
            <Border x:Name="innerBorder" BorderBrush="#FFACACAC" BorderThickness="1,1,1,0" Background="#FFFFCDCD" Margin="-1" Opacity="0"/>
        </Border>
        <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" Focusable="False" HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
    </Grid>
    <ControlTemplate.Triggers>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="false" />
                <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Top" />
            </MultiDataTrigger.Conditions>
            <Setter Property="Opacity" TargetName="mainBorder" Value="0.5"/>
            <Setter Property="Margin" TargetName="mainBorder" Value="-2,-2,-2,0"/>
        </MultiDataTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

フォローする