wpfcontroltemplatemultidatatrigger

WPF - Change button templated text color on DataTrigger


I have a button that has a control template set (including some controltemplate triggers), and I want to change its text color upon a DataTrigger. I've read that I cannot access the TargetName ("theContent") of the template as it has its own scope, so how can I achieve this?

  <Button BorderThickness="0" MaxWidth="94" Height="26" Margin="1,0,0,0">
        <Button.Style>
            <Style TargetType="Button">                        
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Border x:Name="theBorder" CornerRadius="15" BorderThickness="0" Background="{TemplateBinding Background}">
                                <Label x:Name="theContent" VerticalContentAlignment="Center" Foreground="White" FontWeight="Bold">
                                    <TextBlock Text="..." TextTrimming="CharacterEllipsis"></TextBlock>
                                </Label>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="False">
                                    <Setter Property="Background" Value="#1A65AF"></Setter>
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" Value="#4d87c0"></Setter>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="True">
                                    <Setter Property="Background" Value="#004b95"></Setter>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{...}" Value="..."></Condition>
                            <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" Value="False"></Condition>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Background" Value="#ad4811"/>
                        <Setter Property="Foreground" Value="#7F7F7F" /> // does nothing
                        <Setter TargetName="theContent" Property="Foreground" Value="#7F7F7F" /> // target not found
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
        <!--<Button.Content>
            <Label x:Name="theContent" VerticalContentAlignment="Center" Foreground="White" FontWeight="Bold">
                <TextBlock Text="..." TextTrimming="CharacterEllipsis"></TextBlock>
            </Label>
        </Button.Content>-->
    </Button>

The 2 setters that I tried and don't work are these:

<Setter Property="Foreground" Value="#7F7F7F" /> // does nothing
<Setter TargetName="theContent" Property="Foreground" Value="#7F7F7F" /> // target not found

Solution

  • In your control template, you just need to use TemplateBinding rather than hardcoding the value to White.

    <Border x:Name="theBorder" CornerRadius="15" BorderThickness="0" Background="{TemplateBinding Background}">
      <Label x:Name="theContent" VerticalContentAlignment="Center" Foreground="{TemplateBinding Foreground}" FontWeight="Bold">
        <TextBlock Text="..." TextTrimming="CharacterEllipsis"></TextBlock>
      </Label>
    </Border>
    

    Doing that will defer to the button Foreground property. Generally, if any properties need to change in your ControlTemplate dynamically, you will want to use TemplateBinding (for example the FontWeight property). Now your StyleTrigger setter will work as expected.

    Btw, Foreground="{TemplateBinding Foreground}" is just shorthand for

    Foreground="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}"