Search code examples
wpfxamltabcontrolcontroltemplatetabitem

How to change the foreground of the header text of a WPF tabitem onClick?


How can I change only the foreground color of a TabItem header text when it is selected or active without changing the foreground of any item inside that TabItemor anything? I'm new to all this so finding it difficult to figure out where in my TabItemstyling can I implement this little feature and how.

The TabControl style I'm using is:

<Style
    x:Key="{x:Type TabControl}"
    TargetType="{x:Type TabControl}">
    <Setter
        Property="BorderThickness"
        Value="0" />
    <Setter
        Property="BorderBrush"
        Value="Transparent" />
    <Setter
        Property="Background"
        Value="Transparent" />
    <Setter
        Property="Template">
        <Setter.Value>
            <ControlTemplate
                TargetType="TabControl">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition
                            Height="Auto" />
                        <RowDefinition
                            Height="*" />
                    </Grid.RowDefinitions>
                    <Border
                        BorderThickness="0,0,1,1"
                        BorderBrush="#D0CEBF"
                        Grid.Row="1">
                        <Border
                            BorderThickness="{TemplateBinding BorderThickness}"
                            BorderBrush="{TemplateBinding BorderBrush}">
                            <Border
                                Background="{TemplateBinding Background}">
                                <ContentPresenter
                                    ContentSource="SelectedContent" />
                            </Border>
                        </Border>
                    </Border>
                    <TabPanel
                        Grid.Row="0"
                        IsItemsHost="true"
                        HorizontalAlignment="Center" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style
    TargetType="TabItem">
    <Setter
        Property="BorderThickness"
        Value="0" />
    <Setter
        Property="BorderBrush"
        Value="Transparent" />
    <Setter
        Property="Background"
        Value="Transparent" />
    <Setter
        Property="VerticalContentAlignment"
        Value="Center" />
    <Setter
        Property="HorizontalContentAlignment"
        Value="Center" />
    <Setter
        Property="Template">
        <Setter.Value>
            <ControlTemplate
                TargetType="{x:Type TabItem}">
                <!--In order to click on the blank part of the TabItem can be successfully selected-->
                <Border
                    Background="Transparent">
                    <Grid>
                        <Grid
                            x:Name="g">
                            <Path
                                Fill="{TemplateBinding Background}"
                                Margin="0,0,0,-1"
                                Data="M 20,40 L 0,40 0,40 C 4,40 10,36 10,30 L 10,10 C 10,0 16,0 20,0 L 155,0  C 165,0 173,0 ,175,6 L175,30 C 175,30 175,38 182,40 Z" />
                        </Grid>
                        <Border
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Padding="{TemplateBinding Padding}">
                            <ContentPresenter
                                ContentSource="Header"
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                        </Border>
                    </Grid>
                </Border>
                <!--Add ControlTemplate.Triggers to change the background color of the selected TabItem.-->
                <ControlTemplate.Triggers>
                    <Trigger
                        Property="IsSelected"
                        Value="false">
                        <Setter
                            Property="Visibility"
                            TargetName="g"
                            Value="Hidden" />
                    </Trigger>
                
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Solution

  • Adding a trigger in your TabItem control template unfortunately sets the foreground color of the TabItem content, too, when the tab is selected, so this does not work.

    <Trigger Property="IsSelected" Value="True">
       <Setter Property="Foreground" Value="Red" />
    </Trigger>
    

    However, you could add an implicit TextBlock style (without x:Key) inside the ContentPresenter resources. It will be applied automatically only to TextBlocks inside of its scope, not affecting the TabItem content or even other elements in a custom header template other than TextBlocks.

    <ContentPresenter
        ContentSource="Header"
        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
        VerticalAlignment="{TemplateBinding VerticalContentAlignment}" >
       <ContentPresenter.Resources>
          <Style TargetType="{x:Type TextBlock}">
             <Style.Triggers>
                <DataTrigger
                   Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type TabItem}}}"
                   Value="true">
                   <Setter
                      Property="Foreground"
                      Value="Red" />
                </DataTrigger>
             </Style.Triggers>
          </Style>
       </ContentPresenter.Resources>
    </ContentPresenter>
    

    Alternatively, a specialized solution is to create a header template and put the trigger there. In this case it does not force an overridden header template to apply the foreground to each TextBlock.

    <Setter
        Property="HeaderTemplate">
       <Setter.Value>
          <DataTemplate>
             <TextBlock Text="{Binding}">
                <TextBlock.Style>
                   <Style TargetType="{x:Type TextBlock}">
                      <Style.Triggers>
                         <DataTrigger
                            Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type TabItem}}}"
                            Value="true">
                            <Setter
                               Property="Foreground"
                               Value="Red" />
                         </DataTrigger>
                      </Style.Triggers>
                   </Style>
                </TextBlock.Style>
             </TextBlock>
          </DataTemplate>
       </Setter.Value>
    </Setter>