Property Animation Techniques Overview

This topic describes the different approaches for animating properties: storyboards, local animations, clocks, and per-frame animations.

Prerequisites

To understand this topic, you should be familiar with the basic animation features described in the Animation Overview.

Different Ways to Animate

Because there are many different scenarios for animating properties, WPF provides several approaches for animating properties.

For each approach, the following table indicates whether it can be used per-instance, in styles, in control templates, or in data templates; whether it can be used in XAML; and whether the approach enables you to interactively control the animation. "Per-Instance" refers to the technique of applying an animation or storyboard directly to instances of an object, rather than in a style, control template, or data template.

Animation technique Scenarios Supports XAML Interactively controllable
Storyboard animation Per-instance, Style, ControlTemplate, DataTemplate Yes Yes
Local animation Per-instance No No
Clock animation Per-instance No Yes
Per-frame animation Per-instance No N/A

Storyboard Animations

Use a Storyboard when you want to define and apply your animations in XAML, interactively control your animations after they start, create a complex tree of animations, or animate in a Style, ControlTemplate or DataTemplate. For an object to be animated by a Storyboard, it must be a FrameworkElement or FrameworkContentElement, or it must be used to set a FrameworkElement or FrameworkContentElement. For more details, see the Storyboards Overview.

A Storyboard is a special type of container Timeline that provides targeting information for the animations it contains. To animate with a Storyboard, you complete the following three steps.

  1. Declare a Storyboard and one or more animations.

  2. Use the TargetName and TargetProperty attached properties to specify the target object and property of each animation.

  3. (Code only) Define a NameScope for a FrameworkElement or FrameworkContentElement. Register the names of the objects to animate with that FrameworkElement or FrameworkContentElement.

  4. Begin the Storyboard.

Beginning a Storyboard applies animations to the properties they animate and starts them. There are two ways to begin a Storyboard: you can use the Begin method provided by the Storyboard class, or you can use a BeginStoryboard action. The only way to animate in XAML is to use a BeginStoryboard action. A BeginStoryboard action can be used in an EventTrigger, property Trigger, or a DataTrigger.

The following table shows the different places where each Storyboard begin technique is supported: per-instance, style, control template, and data template.

Storyboard is begun using… Per-instance Style Control template Data template Example
BeginStoryboard and an EventTrigger Yes Yes Yes Yes Animate a Property by Using a Storyboard
BeginStoryboard and a property Trigger No Yes Yes Yes Trigger an Animation When a Property Value Changes
BeginStoryboard and a DataTrigger No Yes Yes Yes How to: Trigger an Animation When Data Changes
Begin method Yes No No No Animate a Property by Using a Storyboard

For more information about Storyboard objects, see the Storyboards Overview.

Local Animations

Local animations provide a convenient way to animate a dependency property of any Animatable object. Use local animations when you want to apply a single animation to a property and you don't need to interactively control the animation after it starts. Unlike a Storyboard animation, a local animation can animate an object that isn't associated with a FrameworkElement or a FrameworkContentElement. You also don't have to define a NameScope for this type of animation.

Local animations may only be used in code, and cannot be defined in styles, control templates, or data templates. A local animation cannot be interactively controlled after it is started.

To animate using a local animation, complete the following steps.

  1. Create an AnimationTimeline object.

  2. Use the BeginAnimation method of the object that you want to animate to apply the AnimationTimeline to the property that you specify.

The following example shows how to animate the width and background color of a Button.

/*

   This sample demonstrates how to apply non-storyboard animations to a property.
   To animate in markup, you must use storyboards.

*/

using namespace System;
using namespace System::Windows;
using namespace System::Windows::Navigation;
using namespace System::Windows::Media;
using namespace System::Windows::Media::Animation;
using namespace System::Windows::Shapes;
using namespace System::Windows::Controls;


namespace Microsoft {
   namespace Samples {
      namespace Animation {
         namespace LocalAnimations {
            // Create the demonstration.
            public ref class LocalAnimationExample : Page {

            public: 
               LocalAnimationExample ()
               {
                  WindowTitle = "Local Animation Example";
                  StackPanel^ myStackPanel = gcnew StackPanel();
                  myStackPanel->Margin = Thickness(20);

                  // Create and set the Button.
                  Button^ aButton = gcnew Button();
                  aButton->Content = "A Button";

                  // Animate the Button's Width.
                  DoubleAnimation^ myDoubleAnimation = gcnew DoubleAnimation();
                  myDoubleAnimation->From = 75;
                  myDoubleAnimation->To = 300;
                  myDoubleAnimation->Duration = Duration(TimeSpan::FromSeconds(5));
                  myDoubleAnimation->AutoReverse = true;
                  myDoubleAnimation->RepeatBehavior = RepeatBehavior::Forever;

                  // Apply the animation to the button's Width property.
                  aButton->BeginAnimation(Button::WidthProperty, myDoubleAnimation);

                  // Create and animate a Brush to set the button's Background.
                  SolidColorBrush^ myBrush = gcnew SolidColorBrush();
                  myBrush->Color = Colors::Blue;

                  ColorAnimation^ myColorAnimation = gcnew ColorAnimation();
                  myColorAnimation->From = Colors::Blue;
                  myColorAnimation->To = Colors::Red;
                  myColorAnimation->Duration = Duration(TimeSpan::FromMilliseconds(7000));
                  myColorAnimation->AutoReverse = true;
                  myColorAnimation->RepeatBehavior = RepeatBehavior::Forever;

                  // Apply the animation to the brush's Color property.
                  myBrush->BeginAnimation(SolidColorBrush::ColorProperty, myColorAnimation);
                  aButton->Background = myBrush;

                  // Add the Button to the panel.
                  myStackPanel->Children->Add(aButton);
                  this->Content = myStackPanel;
               };
            };
         }
      }
   }
}
/*

   This sample demonstrates how to apply non-storyboard animations to a property.
   To animate in markup, you must use storyboards.

*/

using System;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls;

namespace Microsoft.Samples.Animation.LocalAnimations
{

    // Create the demonstration.
    public class LocalAnimationExample : Page
    {

        public LocalAnimationExample()
        {

            WindowTitle = "Local Animation Example";
            StackPanel myStackPanel = new StackPanel();
            myStackPanel.Margin = new Thickness(20);

            // Create and set the Button.
            Button aButton = new Button();
            aButton.Content = "A Button";

            // Animate the Button's Width.
            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 75;
            myDoubleAnimation.To = 300;
            myDoubleAnimation.Duration =  new Duration(TimeSpan.FromSeconds(5));
            myDoubleAnimation.AutoReverse = true;
            myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

            // Apply the animation to the button's Width property.
            aButton.BeginAnimation(Button.WidthProperty, myDoubleAnimation);

            // Create and animate a Brush to set the button's Background.
            SolidColorBrush myBrush = new SolidColorBrush();
            myBrush.Color = Colors.Blue;

            ColorAnimation myColorAnimation = new ColorAnimation();
            myColorAnimation.From = Colors.Blue;
            myColorAnimation.To = Colors.Red;
            myColorAnimation.Duration =  new Duration(TimeSpan.FromMilliseconds(7000));
            myColorAnimation.AutoReverse = true;
            myColorAnimation.RepeatBehavior = RepeatBehavior.Forever;

            // Apply the animation to the brush's Color property.
            myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation);
            aButton.Background = myBrush;

            // Add the Button to the panel.
            myStackPanel.Children.Add(aButton);
            this.Content = myStackPanel;
        }
    }
}
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''This sample demonstrates how to apply non-storyboard animations to a property.
'''To animate in markup, you must use storyboards.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Imports System.Windows
Imports System.Windows.Navigation
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes
Imports System.Windows.Controls

Namespace Microsoft.Samples.Animation.LocalAnimations

    ' Create the demonstration.
    Public Class LocalAnimationExample
        Inherits Page

        Public Sub New()

            WindowTitle = "Animate Property Example"
            Dim myStackPanel As New StackPanel()
            myStackPanel.Margin = New Thickness(20)

            ' Create and set the Button.
            Dim aButton As New Button()
            aButton.Content = "A Button"

            ' Animate the Button's Width.
            Dim myDoubleAnimation As New DoubleAnimation()
            myDoubleAnimation.From = 75
            myDoubleAnimation.To = 300
            myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(5))
            myDoubleAnimation.AutoReverse = True
            myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever

            ' Apply the animation to the button's Width property.
            aButton.BeginAnimation(Button.WidthProperty, myDoubleAnimation)

            ' Create and animate a Brush to set the button's Background.
            Dim myBrush As New SolidColorBrush()
            myBrush.Color = Colors.Blue

            Dim myColorAnimation As New ColorAnimation()
            myColorAnimation.From = Colors.Blue
            myColorAnimation.To = Colors.Red
            myColorAnimation.Duration = New Duration(TimeSpan.FromMilliseconds(7000))
            myColorAnimation.AutoReverse = True
            myColorAnimation.RepeatBehavior = RepeatBehavior.Forever

            ' Apply the animation to the brush's Color property.
            myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation)
            aButton.Background = myBrush

            ' Add the Button to the panel.
            myStackPanel.Children.Add(aButton)
            Me.Content = myStackPanel
        End Sub
    End Class
End Namespace

Clock Animations

Use Clock objects when you want to animate without using a Storyboard and you want to create complex timing trees or interactively control animations after they start. You can use Clock objects to animate a dependency property of any Animatable object.

You cannot use Clock objects directly to animate in styles, control templates, or data templates. (The animation and timing system actually does use Clock objects to animate in styles, control templates, and data templates, but it must create those Clock objects for you from a Storyboard. For more information about the relationship between Storyboard objects and Clock objects, see the Animation and Timing System Overview.)

To apply a single Clock to a property, you complete the following steps.

  1. Create an AnimationTimeline object.

  2. Use the CreateClock method of the AnimationTimeline to create an AnimationClock.

  3. Use the ApplyAnimationClock method of the object that you want to animate to apply the AnimationClock to the property you specify.

The following example shows how to create an AnimationClock and apply it to two similar properties.

/*
    This example shows how to create and apply
    an AnimationClock.
*/

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace Microsoft.Samples.Animation.TimingBehaviors
{
    public class AnimationClockExample : Page
    {

        ScaleTransform myScaleTransform;

        public AnimationClockExample()
        {

            this.WindowTitle = "Opacity Animation Example";
            this.Background = Brushes.White;
            StackPanel myStackPanel = new StackPanel();
            myStackPanel.Margin = new Thickness(20);

            // Create a button that with a ScaleTransform.
            // The ScaleTransform will animate when the
            // button is clicked.
            Button myButton = new Button();
            myButton.Margin = new Thickness(50);
            myButton.HorizontalAlignment = HorizontalAlignment.Left;
            myButton.Content = "Click Me";
            myScaleTransform = new ScaleTransform(1,1);
            myButton.RenderTransform = myScaleTransform;

            // Associate an event handler with the
            // button's Click event.
            myButton.Click += new RoutedEventHandler(myButton_Clicked);

            myStackPanel.Children.Add(myButton);
            this.Content = myStackPanel;
        }

        // Create and apply and animation when the button is clicked.
        private void myButton_Clicked(object sender, RoutedEventArgs e)
        {

            // Create a DoubleAnimation to animate the
            // ScaleTransform.
            DoubleAnimation myAnimation =
                new DoubleAnimation(
                    1, // "From" value
                    5, // "To" value
                    new Duration(TimeSpan.FromSeconds(5))
                );
            myAnimation.AutoReverse = true;

            // Create a clock the for the animation.
            AnimationClock myClock = myAnimation.CreateClock();

            // Associate the clock the ScaleX and
            // ScaleY properties of the button's
            // ScaleTransform.
            myScaleTransform.ApplyAnimationClock(
                ScaleTransform.ScaleXProperty, myClock);
            myScaleTransform.ApplyAnimationClock(
                ScaleTransform.ScaleYProperty, myClock);
        }
    }
}
'
'    This example shows how to create and apply
'    an AnimationClock.
'


Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation


Namespace Microsoft.Samples.Animation.TimingBehaviors
    Public Class AnimationClockExample
        Inherits Page

        Private ReadOnly myScaleTransform As ScaleTransform

        Public Sub New()

            WindowTitle = "Opacity Animation Example"
            Background = Brushes.White
            Dim myStackPanel As New StackPanel With {
                .Margin = New Thickness(20)
            }

                ' Create a button that with a ScaleTransform.
                ' The ScaleTransform will animate when the
                ' button is clicked.
            Dim myButton As New Button With {
                .Margin = New Thickness(50),
                .HorizontalAlignment = HorizontalAlignment.Left,
                .Content = "Click Me"
            }
            myScaleTransform = New ScaleTransform(1,1)
            myButton.RenderTransform = myScaleTransform


            ' Associate an event handler with the
            ' button's Click event.
            AddHandler myButton.Click, AddressOf myButton_Clicked

            myStackPanel.Children.Add(myButton)
            Content = myStackPanel
        End Sub

        ' Create and apply and animation when the button is clicked.
        Private Sub myButton_Clicked(sender As Object, e As RoutedEventArgs)

            ' Create a DoubleAnimation to animate the
            ' ScaleTransform.
            Dim myAnimation As New DoubleAnimation(1, 5, New Duration(TimeSpan.FromSeconds(5))) With {
                .AutoReverse = True
            } ' "To" value -  "From" value

            ' Create a clock the for the animation.
            Dim myClock As AnimationClock = myAnimation.CreateClock()

            ' Associate the clock the ScaleX and
            ' ScaleY properties of the button's
            ' ScaleTransform.
            myScaleTransform.ApplyAnimationClock(ScaleTransform.ScaleXProperty, myClock)
            myScaleTransform.ApplyAnimationClock(ScaleTransform.ScaleYProperty, myClock)
        End Sub
    End Class
End Namespace

To create a timing tree and use it animate properties, you complete the following steps.

  1. Use ParallelTimeline and AnimationTimeline objects to create the timing tree.

  2. Use the CreateClock of the root ParallelTimeline to create a ClockGroup.

  3. Iterate through the Children of the ClockGroup and apply its child Clock objects. For each AnimationClock child, use the ApplyAnimationClock method of the object that you want to animate to apply the AnimationClock to the property you specify

For more information about Clock objects, see the Animation and Timing System Overview.

Per-Frame Animation: Bypass the Animation and Timing System

Use this approach when you need to completely bypass the WPF animation system. One scenario for this approach is physics animations, where each step in the animation requires objects to be recomputed based on the last set of object interactions.

Per-frame animations cannot be defined inside styles, control templates, or data templates.

To animate frame-by-frame, you register for the Rendering event of the object that contains the objects you want to animate. This event handler method gets called once per frame. Each time that WPF marshals the persisted rendering data in the visual tree across to the composition tree, your event handler method is called.

In your event handler, perform whatever calculations are necessary for your animation effect and set the properties of the objects you want to animate with these values.

To obtain the presentation time for the current frame, the EventArgs associated with this event can be cast as RenderingEventArgs, which provide a RenderingTime property that you can use to obtain the current frame's rendering time.

For more information, see the Rendering page.

See also