wpfxamltriggerscontroltemplatetargettype

WPF - Is there a way to target an element type in a ControlTemplate's trigger?


I have the following ControlTemplate defined:

<ControlTemplate x:Key="buttonTemplate" TargetType="{x:Type Button}">
    <Border x:Name="buttonBorder">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TextBlock x:Name="txtLabel" Grid.Column="0">
                <ContentPresenter/>
            </TextBlock>
            <Canvas x:Name="reschedule" Grid.Column="1">
                <Path x:Name="path1" ... />
                <Path x:Name="path2" ... />
                <Path x:Name="path3" ... />
                <Path x:Name="path4" ... />
                <Path x:Name="path5" ... />
                <Path x:Name="path6" ... />
                <Path x:Name="path7" ... />
                <Path x:Name="path8" ... />
                <Path x:Name="path9" ... />
                <Path x:Name="path10" ... />
            </Canvas>
        </Grid>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter TargetName="buttonBorder" Property="Background" Value="DarkGreen"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter TargetName="buttonBorder" Property="Background" Value="DarkGray"/>
            <Setter TargetName="txtLabel" Property="Foreground" Value="Gray"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

Right now the default TextBlock Foreground and Path Fill properties have been set to White. When the button is disabled I want to set those properties to Gray. Right now it works for the TextBlock and I can make it work for the Paths too by targetting each of their names, but is there a way to target all the Path elements by type? Something like:

<Setter TargetType="Path" Property="Fill" Value="Gray"/>

I've tried adding the following trigger to the Border element's style but it doesn't work:

<Border.Style>
    <Style TargetType="Border">
        <Style.Resources>
            <Style TargetType="Path">
                <Style.Triggers>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Fill" Value="Gray"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Style.Resources>
    </Style>
</Border.Style>

Solution

  • You can try this trick:

    Create a proxy control for Binding:

    <Control x:Name="Proxy" Background="White" /> 
    

    And use in Path binding like this:

    <Path x:Name="path1" Fill="{Binding Path=Background, ElementName=Proxy}" Data="..." />
    

    When you're in the Trigger set the color for the Proxy, his tucked up all the Path's.

    Or instead of the binding Proxy, you can use any existing controls, such TextBlock.

    Full example:

    <ControlTemplate x:Key="buttonTemplate" TargetType="{x:Type Button}">
        <Border x:Name="buttonBorder">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
    
                <TextBlock x:Name="txtLabel" Grid.Column="0">                        
                    <ContentPresenter />
                </TextBlock>
    
                <Control x:Name="Proxy" Background="White" /> 
    
                <Canvas x:Name="reschedule" Grid.Column="1">
                    <Path x:Name="path1" Fill="{Binding Path=Background, ElementName=Proxy}" Data="..." />
                    <Path x:Name="path2" Fill="{Binding Path=Background, ElementName=Proxy}" Data="..." />
                </Canvas>
            </Grid>
        </Border>
    
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter TargetName="buttonBorder" Property="Background" Value="DarkGreen" />
            </Trigger>
    
            <Trigger Property="IsEnabled" Value="False">
                <Setter TargetName="buttonBorder" Property="Background" Value="DarkGray" />
                <Setter TargetName="txtLabel" Property="Foreground" Value="Gray" />
                <Setter TargetName="Proxy" Property="Background" Value="Gray" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>