WPF stop and reverse Storyboard animation when new animation starts

1.6k Views Asked by At

I have 2 DataTrigger that animates the background color of a button (with reverse), this part works fine.

The problem is that when the 2 triggers are fired in overlapping times, the first trigger fired does not reverse the color, when the second trigger stops it reverses the color to whatever was the color when the previous animation stopped.

What should I do?

This is the example code:

<DataTrigger Binding="{Binding IsUp}" Value="True">
    <DataTrigger.EnterActions>
        <StopStoryboard BeginStoryboardName="isDownStoryBoard"/>
            <BeginStoryboard Name="isUpStoryBoard">
                <Storyboard>
                    <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[0].Color" To="#b4e391" Duration="0:0:1" AutoReverse="True" RepeatBehavior="2x" />
                    <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[1].Color" To="#61c419" Duration="0:0:1" AutoReverse="True" RepeatBehavior="2x" />
                    <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[2].Color" To="#b4e391" Duration="0:0:1" AutoReverse="True" RepeatBehavior="2x" />
                    <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[3].Color" To="#b4e391" Duration="0:0:1" AutoReverse="True" RepeatBehavior="2x" />                           
            </Storyboard>                                                                                                                                     
        </BeginStoryboard>                                                                                                                                    
    </DataTrigger.EnterActions>                                                                                                                                                                                   
</DataTrigger>                                                                                                                                                

<DataTrigger Binding="{Binding IsDown}" Value="True">                                                                                                         
    <DataTrigger.EnterActions>
        <StopStoryboard BeginStoryboardName="isUpStoryBoard"/>
            <BeginStoryboard Name="isDownStoryBoard">                                                                                                                                     
                <Storyboard>                                                                                                                                      
                    <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[0].Color" To="#efc5ca" Duration="0:0:1" AutoReverse="True" RepeatBehavior="2x" />
                    <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[1].Color" To="#d24b5a" Duration="0:0:1" AutoReverse="True" RepeatBehavior="2x" />
                    <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[2].Color" To="#ba2737" Duration="0:0:1" AutoReverse="True" RepeatBehavior="2x" />
                    <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[3].Color" To="#f18e99" Duration="0:0:1" AutoReverse="True" RepeatBehavior="2x" />
            </Storyboard>
        </BeginStoryboard>
    </DataTrigger.EnterActions>     
</DataTrigger>   
1

There are 1 best solutions below

2
On

There is a StopStoryboard Class that you can use to stop a running Storyboard with, but there is no ReverseStoryboard class. However, you can just create another Storyboard that runs in reverse to your original one that you start when you stop the original one. You can use the StopStoryboard class like this (from the linked page on MSDN):

<!-- Begin the Storyboard -->
<EventTrigger RoutedEvent="Button.Click" SourceName="BeginButton">
  <BeginStoryboard Name="MyBeginStoryboard">
    <Storyboard >
      <DoubleAnimation 
        Storyboard.TargetName="myRectangle" 
        Storyboard.TargetProperty="Width" 
        Duration="0:0:5" From="100" To="500" />
    </Storyboard>
  </BeginStoryboard>
</EventTrigger>

...

<!-- Stop the Storyboard -->
<EventTrigger RoutedEvent="Button.Click" SourceName="StopButton">
  <StopStoryboard BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>

Also, please see the Timeline.FillBehavior Property that you can set on the Storyboard which Gets or sets a value that specifies how the Timeline behaves after it reaches the end of its active period. You can set it to the FillBehavior.HoldEnd enumeration to get the Storyboard to keep it's last value when it ends.