How to: Set a Property After Animating It with a Storyboard

 

In some cases, it might appear that you can't change the value of a property after it has been animated.

In the following example, a Storyboard is used to animate the color of a SolidColorBrush. The storyboard is triggered when the button is clicked. The Completed event is handled so that the program is notified when the ColorAnimation completes.

    <Button
      Content="Animate and Then Set Example 1">
      <Button.Background>
        <SolidColorBrush x:Name="Button1BackgroundBrush"
          Color="Red" />
      </Button.Background>
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard>
            <Storyboard>
              <ColorAnimation
                Storyboard.TargetName="Button1BackgroundBrush"
                Storyboard.TargetProperty="Color"
                From="Red" To="Yellow" Duration="0:0:5"
                FillBehavior="HoldEnd"
                Completed="setButton1BackgroundBrushColor" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>
    </Button>

After the ColorAnimation completes, the program attempts to change the brush's color to blue.

		Private Sub setButton1BackgroundBrushColor(ByVal sender As Object, ByVal e As EventArgs)

			' Does not appear to have any effect:
			' the brush remains yellow.
			Button1BackgroundBrush.Color = Colors.Blue
		End Sub

The previous code doesn't appear to do anything: the brush remains yellow, which is the value supplied by the ColorAnimation that animated the brush. The underlying property value (the base value) is actually changed to blue. However, the effective, or current, value remains yellow because the ColorAnimation is still overriding the base value. If you want the base value to become the effective value again, you must stop the animation from influencing the property. There are three ways to do this with storyboard animations:

  • Set the animation's FillBehavior property to Stop

  • Remove the entire Storyboard.

  • Remove the animation from the individual property.

By setting FillBehavior to Stop, you tell the animation to stop affecting its target property after it reaches the end of its active period.

    <Button
      Content="Animate and Then Set Example 2">
      <Button.Background>
        <SolidColorBrush x:Name="Button2BackgroundBrush"
          Color="Red" />
      </Button.Background>
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard>
            <Storyboard>
              <ColorAnimation
                Storyboard.TargetName="Button2BackgroundBrush"
                Storyboard.TargetProperty="Color"
                From="Red" To="Yellow" Duration="0:0:5"
                FillBehavior="Stop"
                Completed="setButton2BackgroundBrushColor" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>
    </Button>

		Private Sub setButton2BackgroundBrushColor(ByVal sender As Object, ByVal e As EventArgs)

			' This appears to work:
			' the brush changes to blue.
			Button2BackgroundBrush.Color = Colors.Blue
		End Sub

By using a RemoveStoryboard trigger or the Storyboard.Remove method, you tell the storyboard animations to stop affecting their target properties. The difference between this approach and setting the FillBehavior property is that you can remove the storyboard at anytime, while the FillBehavior property only has an effect when the animation reaches the end of its active period.

    <Button
      Name="Button3"
      Content="Animate and Then Set Example 3">
      <Button.Background>
        <SolidColorBrush x:Name="Button3BackgroundBrush"
          Color="Red" />
      </Button.Background>
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard Name="MyBeginStoryboard">
            <Storyboard x:Name="MyStoryboard">
              <ColorAnimation
                Storyboard.TargetName="Button3BackgroundBrush"
                Storyboard.TargetProperty="Color"
                From="Red" To="Yellow" Duration="0:0:5"
                FillBehavior="HoldEnd"
                Completed="setButton3BackgroundBrushColor" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>
    </Button>

		Private Sub setButton3BackgroundBrushColor(ByVal sender As Object, ByVal e As EventArgs)

			 ' This appears to work:
			' the brush changes to blue.
			MyStoryboard.Remove(Button3)
			Button3BackgroundBrush.Color = Colors.Blue
		End Sub

Another technique to stop an animation from affecting a property is to use the BeginAnimation(DependencyProperty, AnimationTimeline) method of the object being animated. Specify the property being animated as the first parameter and null as the second.

    <Button
      Name="Button4"
      Content="Animate and Then Set Example 4">
      <Button.Background>
        <SolidColorBrush x:Name="Button4BackgroundBrush"
          Color="Red" />
      </Button.Background>
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard>
            <Storyboard>
              <ColorAnimation
                Storyboard.TargetName="Button4BackgroundBrush"
                Storyboard.TargetProperty="Color"
                From="Red" To="Yellow" Duration="0:0:5"
                FillBehavior="HoldEnd"
                Completed="setButton4BackgroundBrushColor" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>
    </Button>

		Private Sub setButton4BackgroundBrushColor(ByVal sender As Object, ByVal e As EventArgs)

			 ' This appears to work:
			' the brush changes to blue.
			Button4BackgroundBrush.BeginAnimation(SolidColorBrush.ColorProperty, Nothing)
			Button4BackgroundBrush.Color = Colors.Blue
		End Sub

This technique also works for non-storyboard animations.

FillBehavior
Storyboard.Remove
RemoveStoryboard
Animation Overview
Property Animation Techniques Overview

Show: