Search code examples
wpfxamldatatrigger

Style trigger based on parent style property


I want to have buttons with little icons as content.

The icons are defined and stored in a ResourceDictionary like this:

<Path x:Key="BackIcon" Data="F1 M 57,42L 57,34L 32.25,34L 42.25,24L 31.75,24L 17... "/>
<Path x:Key="LoadFromFileIcon" Data="F1 M 48,39L 56,39L 56,49L 63.25,49L 52,60.2... "/>
<Path x:Key="SaveToFileIcon" Data="F1 M 48,60L 56,60L 56,50L 63.25,50L 52,38.75L... "/>

Since I also need to provide Path.Fill, Path.Stretch etc. properties, I decided to make my own IconButtonStyle so I won't have to repeat the same attribute in every Path in the icon dictionary and make buttons very easily like this:

<Button Style="{StaticResource IconButtonStyle}"
    Content="{StaticResource ResetIcon}"/>

This is what I came up with:

<Style x:Key="IconButtonStyle" TargetType="Button">
    <Style.Resources>
        <Style TargetType="Path">
            <Setter Property="Fill" Value="Black"/> <!-- Default path fill. -->

            <Style.Triggers>
                <!-- How can I set path fill to "Red" based on the parent Button IsEnabled property? -->
            </Style.Triggers>
        </Style>
    </Style.Resources>

    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="false">
            <!-- ?? -->
        </Trigger>
    </Style.Triggers>

</Style>

My custom icon buttons have default path style defined via Style.Resources. Setting default path fill is easy but I can't figure out how to set a trigger that'll change path's fill to red when the owner button is disabled.

Is it even possible?


Solution

  • Okay... I guess you need to modify a few things before proceeding. First in XAML you should use a code like this:

    <Button Style="{DynamicResource IconButtonStyle}" IsEnabled="False" Content="{StaticResource _rect}">
        </Button>
    

    In this case I used a rectangle which I defined in Resources. this is the code for rectangle:

        <Rectangle Width="10" Height="10" Style="{StaticResource ContentButtonPathStyle}" x:Key="_rect"></Rectangle>
    

    you will obviously use your paths instead of rectangles... You notice that the Style is set to ContentButtonPathStyle .

    This is the code for that style:

    <Style x:Key="ContentButtonPathStyle" TargetType="{x:Type Rectangle}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource=
                    {RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path=IsEnabled}" Value="False">
                    <Setter Property="Fill" Value="Red"/>
                </DataTrigger>
    
                <DataTrigger Binding="{Binding RelativeSource=
                    {RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path=IsEnabled}" Value="True">
                    <Setter Property="Fill" Value="Black"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    

    Note that you must define ContentButtonPathStyle before your rectangle (paths).

    The last thing is that you don't even need to specify a Style for your button. unless you need it for other purposes.