WPF Style Triggers: can I apply the one style for

2019-06-05 02:56发布

问题:

It seems like there has to be a way to do this:

I am applying an ItemContainerStyle in my Listbox, based on two property triggers. As you can see, I'm using the exact same set of trigger enter/exit actions, simply applied on two different properties. Is there something equivalent to a <Trigger Property="prop1" OR Property="prop2"> ??? (Obviously wouldn't look like that, but that probably gets the point across.)

<Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem">
            <Style.Triggers>
                <Trigger Property="IsKeyboardFocusWithin" Value="True">
                    <Trigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Height"
                                        To="50" Duration="0:0:.3"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                    <Trigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Height"
                                              To="25" Duration="0:0:.3" />
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.ExitActions>
                </Trigger>


            </Style.Triggers>


   </Style>
<Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Trigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Height"
                                        To="50" Duration="0:0:.3"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                    <Trigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Height"
                                              To="25" Duration="0:0:.3" />
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.ExitActions>
                </Trigger>


            </Style.Triggers>
</Style>

回答1:

Have you tried any of the following (extracted from Adam Nathan's book: Windows Presentation Foundation Unleashed):

  • Multiple triggers applied to the same element (to get a logical OR).
  • Multiple properties evaluated for the same trigger (to get a logical AND).

Logical OR

Since Style.Triggers can contain multiple triggers, you can create more than one with the exact same Setters to express a logical OR relationship.

For example:

<Style.Triggers>
    <Trigger Property="IsMouseOver" Value="True">
        ...
    </Trigger>
    <Trigger Property="IsKeyboardFocusWithin" Value="True">
        ....
    </Trigger>
</Style.Triggers>

This means, "if IsMouseOver is true or if IsKeyboardFocusWithin is true, apply the action.

Logical AND

To express a logical AND relationship, you can use a variation of Trigger called MultiTrigger, or a variation of DataTrigger called MultiDataTrigger. Both triggers have a collection of Conditions that contain the information you would normally put directly inside a Trigger or DataTrigger.

For example:

<Style.Triggers>
    <MultiTrigger>
    <MultiTrigger.Conditions>
        <Condition Property="IsMouseOver" Value="True"/>
        <Condition Property="IsKeyboardFocusWithin" Value="True"/>
    </MultiTrigger.Conditions>
    </MultiTrigger>
        <Setter ...>
        <Setter ...>
</Style.Triggers>


回答2:

You can put the Storyboards into resources and just reference them in the triggers. It's not exactly what you want, but it allows you to define your animations in one central place (rather than having to copy & paste them).

<Style TargetType="...">
    <Style.Resources>
        <Storyboard x:Key="MyGetFocusAnimation">
            <DoubleAnimation Storyboard.TargetProperty="Height"
                             To="50" Duration="0:0:.3" />
        </Storyboard>
        <Storyboard x:Key="MyLoseFocusAnimation">
            <DoubleAnimation Storyboard.TargetProperty="Height"
                             To="25" Duration="0:0:.3" />
        </Storyboard>
    </Style.Resources>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Trigger.EnterActions>
                <BeginStoryboard Storyboard="{StaticResource MyGetFocusAnimation}" />
            </Trigger.EnterActions>
            <Trigger.ExitActions>
                <BeginStoryboard Storyboard="{StaticResource MyLoseFocusAnimation}" />
            </Trigger.ExitActions>
        </Trigger>
        <Trigger Property="IsKeyboardFocusWithin" Value="True">
            <Trigger.EnterActions>
                <BeginStoryboard Storyboard="{StaticResource MyGetFocusAnimation}" />
            </Trigger.EnterActions>
            <Trigger.ExitActions>
                <BeginStoryboard Storyboard="{StaticResource MyLoseFocusAnimation}" />
            </Trigger.ExitActions>
        </Trigger>
    </Style.Triggers>
</Style>