Multiple storyboards on one property

2019-02-09 09:50发布

问题:

I have multiple storyboards that access the same property (not at the same time). After one storyboard changed the property, the other one seems to have no access to it and does not change anything.. What can I do against this?

Sample:

<ListBox>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <Border Name="Border" BorderBrush="DarkGray" BorderThickness="1" Margin="3">
                            <ContentPresenter />
                            <Border.Background>
                                <SolidColorBrush />
                            </Border.Background>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="True">
                                <Trigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="#3e8bff" Duration="0:0:0.1" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="White" Duration="0:0:0.1" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.ExitActions>
                            </Trigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsMouseOver" Value="True" />
                                    <Condition Property="IsSelected" Value="False" />
                                </MultiTrigger.Conditions>
                                <MultiTrigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="Orange" Duration="0:0:0.1" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </MultiTrigger.EnterActions>
                                <MultiTrigger.ExitActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="White" Duration="0:0:0.1" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </MultiTrigger.ExitActions>
                            </MultiTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.Items>
        <sys:String>hey</sys:String>
        <sys:String>du</sys:String>
        <sys:String>dux</sys:String>
        <sys:String>duy</sys:String>
        <sys:String>dua</sys:String>
    </ListBox.Items>
</ListBox>

This is the smallest sample code I could make. After you've hovered an item, it won't turn blue when it's selected (try to click on one item and then use the arrow keys to select items without hovering them).

回答1:

I have a solution!!! Triggers and actions order does matter... the answer is not to play more then one storyboard at the same time, just stop other.

<ControlTemplate.Triggers>
    <MultiTrigger>
        <MultiTrigger.Conditions>
            <Condition Property="IsMouseOver" Value="True"/>
            <Condition Property="Selector.IsSelected" Value="False" />
        </MultiTrigger.Conditions>
        <MultiTrigger.EnterActions>
            <StopStoryboard BeginStoryboardName="SelectedBegin" />
            <StopStoryboard BeginStoryboardName="UnselectBegin" />
            <BeginStoryboard x:Name="EnterBegin" Storyboard="{StaticResource MouseEnterSb}"/>
        </MultiTrigger.EnterActions>
        <MultiTrigger.ExitActions>
            <BeginStoryboard x:Name="LeaveBegin" Storyboard="{StaticResource MouseLeaveSb}"/>
        </MultiTrigger.ExitActions>
    </MultiTrigger>
    <Trigger Property="Selector.IsSelected" Value="True">
        <Trigger.EnterActions>
            <StopStoryboard BeginStoryboardName="LeaveBegin" />
            <StopStoryboard BeginStoryboardName="EnterBegin" />
            <BeginStoryboard x:Name="SelectedBegin" Storyboard="{StaticResource SelectedSb}"/>
        </Trigger.EnterActions>
        <Trigger.ExitActions>
            <BeginStoryboard x:Name="UnselectBegin" Storyboard="{StaticResource UnselectSb}"/>
        </Trigger.ExitActions>
    </Trigger>
</ControlTemplate.Triggers> 


回答2:

I've been able to reproduce your erroneous results using the following code (I'm stumped too):

<ListBox>
<ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <ControlTemplate.Resources>
                        <Storyboard x:Key="BorderAnimationToRed">
                            <ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="Red" Duration="0:0:0.1" />
                        </Storyboard>
                        <Storyboard x:Key="BorderAnimationToBlue">
                            <ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="Blue" Duration="0:0:0.1" />
                        </Storyboard>
                        <Storyboard x:Key="BorderAnimationToOrange">
                            <ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="Orange" Duration="0:0:0.1" />
                        </Storyboard>
                        <Storyboard x:Key="BorderAnimationToWhite">
                            <ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="White" Duration="0:0:0.1" />
                        </Storyboard>
                    </ControlTemplate.Resources>
                    <Border Name="Border" BorderBrush="DarkGray" BorderThickness="1" Margin="3">
                        <ContentPresenter />
                        <Border.Background>
                            <SolidColorBrush />
                        </Border.Background>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Trigger.EnterActions>
                                <BeginStoryboard Storyboard="{StaticResource BorderAnimationToOrange}"/>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard Storyboard="{StaticResource BorderAnimationToWhite}"/>
                            </Trigger.ExitActions>
                        </Trigger>
                        <Trigger Property="IsSelected" Value="True">
                            <Trigger.EnterActions>
                                <BeginStoryboard Storyboard="{StaticResource BorderAnimationToBlue}"/>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard Storyboard="{StaticResource BorderAnimationToWhite}"/>
                            </Trigger.ExitActions>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ListBox.ItemContainerStyle>
<ListBox.Items>
    <sys:String>hey</sys:String>
    <sys:String>du</sys:String>
    <sys:String>dux</sys:String>
    <sys:String>duy</sys:String>
    <sys:String>dua</sys:String>
</ListBox.Items>

This code is a little easier to read, as the visuals, resources, and triggers are declared separately. Maybe you could try to use EventTriggers to accomplish your goal (using the "ListBoxItem.MouseEnter" and "ListBoxItem.MouseLeave" routed events). Good luck!