Condividi tramite


Animation Overview

Windows Presentation Foundation (WPF) provides a powerful set of graphics and layout features that enable you to create attractive user interfaces and appealing documents. Animation can make an attractive user interface even more spectacular and usable. By just animating a background color or applying an animated Transform, you can create dramatic screen transitions or provide helpful visual cues.

This overview provides an introduction to the WPF animation and timing system. It focuses on the animation of WPF objects by using storyboards.

This topic contains the following sections.

  • Introducing Animations
  • WPF Property Animation System
  • Example: Make an Element Fade In and Out of View
  • Animation Types
  • Applying an Animation to a Property
  • Interactively Control a Storyboard
  • What Happens After an Animation Ends?
  • Data Binding and Animating Animations
  • Other Ways to Animate
  • Animation Samples
  • Related Topics

Introducing Animations

Animation is an illusion that is created by quickly cycling through a series of images, each slightly different from the last. The brain perceives the group of images as a single changing scene. In film, this illusion is created by using cameras that record many photographs, or frames, each second. When the frames are played back by a projector, the audience sees a moving picture.

Animation on a computer is similar. For example, a program that makes a drawing of a rectangle fade out of view might work as follows.

  • The program creates a timer.

  • The program checks the timer at set intervals to see how much time has elapsed.

  • Each time the program checks the timer, it computes the current opacity value for the rectangle based on how much time has elapsed.

  • The program then updates the rectangle with the new value and redraws it.

Prior to WPF, Microsoft Windows developers had to create and manage their own timing systems or use special custom libraries. WPF includes an efficient timing system that is exposed through managed code and Extensible Application Markup Language (XAML) and that is deeply integrated into the WPF framework. WPF animation makes it easy to animate controls and other graphical objects.

WPF handles all the behind-the-scenes work of managing a timing system and redrawing the screen efficiently. It provides timing classes that enable you to focus on the effects you want to create, instead of the mechanics of achieving those effects. WPF also makes it easy to create your own animations by exposing animation base classes from which you can inherit, to produce customized animations. These custom animations gain many of the performance benefits of the standard animation classes.

WPF Property Animation System

If you understand a few important concepts about the timing system, WPF animations can be easier to use. Most important is that, in WPF, you animate objects by applying animation to their individual properties. For example, to make a framework element grow, you animate its Width and Height properties. To make an object fade from view, you animate its Opacity property.

For a property to have animation capabilities, it must meet the following three requirements:

  • It must be a dependency property.

  • It must belong to a class that inherits from DependencyObject and implements the IAnimatable interface.

  • There must be a compatible animation type available. (If Windows Presentation Foundation (WPF) does not provide one, you can create your own. See the Custom Animations Overview.)

WPF contains many objects that have animation properties. Controls such as Button and TabControl, and also Panel and Shape objects inherit from DependencyObject. Most of their properties are dependency properties.

You can use animations almost anywhere, which includes in styles and control templates. Animations do not have to be visual; you can animate objects that are not a part of the user interface as long as they meet the criteria that is described in this section.

Example: Make an Element Fade In and Out of View

This example shows how to use a WPF animation to animate the value of a dependency property. It uses a DoubleAnimation, which is a type of animation that generates Double values, to animate the Opacity property of a Rectangle. As a result, the Rectangle fades in and out of view.

The first part of the example creates a Rectangle element and displays it in a Page. The steps that follow show how to create an animation and apply it to the rectangle's Opacity property.

<Page
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  WindowTitle="Fading Rectangle Example">
  <StackPanel Margin="10">
    
    <Rectangle
      Name="MyRectangle"
      Width="100" 
      Height="100"
      Fill="Blue">
    </Rectangle> 
  </StackPanel>
</Page>

[C#]

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

namespace Microsoft.SDK.Animation
{
    public class RectangleOpacityFadeExample : Page
    {
        public RectangleOpacityFadeExample()
        {
            NameScope.SetNameScope(this, new NameScope());
            this.WindowTitle = "Fading Rectangle Example";
            StackPanel myPanel = new StackPanel();
            myPanel.Margin = new Thickness(10);
            
            Rectangle myRectangle = new Rectangle();
            myRectangle.Name = "myRectangle";
            this.RegisterName(myRectangle.Name, myRectangle);
            myRectangle.Width = 100;
            myRectangle.Height = 100;
            myRectangle.Fill = Brushes.Blue;
            myPanel.Children.Add(myRectangle);
            this.Content = myPanel; 
        }
    }
}

Part 1: Create a DoubleAnimation

One way to make an element fade in and out of view is to animate its Opacity property. Because the Opacity property is of type Double, you need an animation that produces double values. A DoubleAnimation is one such animation. A DoubleAnimation creates a transition between two double values. To specify its starting value, you set its From property. To specify its ending value, you set its To property.

  1. An opacity value of 1.0 makes the object completely opaque, and an opacity value of 0.0 makes it completely invisible. To make the animation transition from 1.0 to 0.0 you set its From property to 1.0 and its To property to 0.0.

    ...
    <DoubleAnimation From="1.0" To="0.0"  />        
    ...
    

    [C#]

    DoubleAnimation myDoubleAnimation = new DoubleAnimation();
    myDoubleAnimation.From = 1.0;
    myDoubleAnimation.To = 0.0;
    
  2. Next, you must specify a Duration. The Duration of an animation specifies how long it takes to go from its starting value to its destination value. In the following example, the animation is given a duration of five seconds.

    ...
    <DoubleAnimation From="1.0" To="0.0" Duration="0:0:5" />        
    ...
    

    [C#]

    myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
    
  3. The previous code showed an animation that transitions from 1.0 to 0.0, which causes the target element to fade from completely opaque to completely invisible. To make the element fade back into view after it vanishes, set the AutoReverse property of the animation to true. To make the animation repeat indefinitely, set its RepeatBehavior property to Forever.

    ...
    <DoubleAnimation From="1.0" To="0.0" Duration="0:0:5" AutoReverse="True" RepeatBehavior="Forever"/>        
    ...
    

    [C#]

    myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
    myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
    

Part 2: Create a Storyboard

To apply an animation to an object, you create a Storyboard and use the TargetName and TargetProperty attached properties to specify the object and property to animate.

  1. Create the Storyboard and add the animation as its child.

    ...
    <Storyboard>
      <DoubleAnimation
        From="1.0" To="0.0" Duration="0:0:1" 
        AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>
    ...
    

    In code, declare the Storyboard as a class member.

    [C#]

    public class RectangleOpacityFadeExample : Page
    { 
        private Storyboard myStoryboard;
    

    Then initialize the Storyboard and add the animation as its child.

    [C#]

    myStoryboard = new Storyboard();
    myStoryboard.Children.Add(myDoubleAnimation);
    
  1. The Storyboard has to know where to apply the animation. Use the System.Windows.Media.Animation.Storyboard.TargetName attached property to specify the object to animate. In the following code, the DoubleAnimation is given a target name of myAnimatedRectangle, which is the name of the object to animate.

    ...
    <Storyboard>
      <DoubleAnimation
        Storyboard.TargetName="MyRectangle" 
        From="1.0" To="0.0" Duration="0:0:1" 
        AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>
    ...
    

    [C#]

    Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
    
NoteNote:

When creating storyboards in code, you must perform two additional steps: create a name scope and register the name of the object to animate. The code at the beginning of this section that created the page and the rectangle also declared a NameScope and registered a name for the rectangle. You use the SetNameScope method to create a NameScope, if one does not already exist. You use the RegisterName method to register the target object's name with the element for which you created a NameScope. Otherwise, the Storyboard is unable to find the object to animate it. For an additional example, see How to: Define a Name Scope.

Part 3 (XAML): Associate the Storyboard with a Trigger

The easiest way to apply and start a Storyboard in XAML is to use an event trigger.

  1. Create a BeginStoryboard object and associate your storyboard with it. A BeginStoryboard is a type of TriggerAction that applies and starts a Storyboard.

    ...
    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Storyboard.TargetName="MyRectangle" 
          Storyboard.TargetProperty="Opacity"
          From="1.0" To="0.0" Duration="0:0:5" 
          AutoReverse="True" RepeatBehavior="Forever" />
      </Storyboard>
    </BeginStoryboard>
    ...
    
  2. Create an EventTrigger and add the BeginStoryboard to its Actions collection. Set the RoutedEvent property of the EventTrigger to the Routed Events Overview that you want to start the Storyboard.

    ...
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimation
            Storyboard.TargetName="MyRectangle" 
            Storyboard.TargetProperty="Opacity"
            From="1.0" To="0.0" Duration="0:0:5" 
            AutoReverse="True" RepeatBehavior="Forever" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
    ...
    

    (For more information about routed events, see the Routed Events Overview.)

  3. Add the EventTrigger to the Triggers collection of the Rectangle.

    ...
    <Rectangle
      Name="MyRectangle"
      Width="100" 
      Height="100"
      Fill="Blue">
      <Rectangle.Triggers>
    
        <!-- Animates the rectangle's opacity. -->
        <EventTrigger RoutedEvent="Rectangle.Loaded">
          <BeginStoryboard>
            <Storyboard>
              <DoubleAnimation
                Storyboard.TargetName="MyRectangle" 
                Storyboard.TargetProperty="Opacity"
                From="1.0" To="0.0" Duration="0:0:5" 
                AutoReverse="True" RepeatBehavior="Forever" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers>
    </Rectangle>
    ...
    

Part 3 (Code): Associate the Storyboard with an Event Handler

The easiest way to apply and start a Storyboard in code is to use an event handler.

  1. Register for the Loaded event of the rectangle.

    [C#]

    myRectangle.Loaded += new RoutedEventHandler(myRectangleLoaded);
    
  2. Declare the event handler. In the event handler, use the Begin method to apply the storyboard.

    [C#]

    ...
    public void myRectangleLoaded(object sender, RoutedEventArgs e)
    {
        myStoryboard.Begin(this);
    }
    ...
    

Complete Example

The following example shows the complete code for creating a rectangle that fades in and out of view.

<Page
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  WindowTitle="Fading Rectangle Example">
  <StackPanel Margin="10">

    <Rectangle
      Name="MyRectangle"
      Width="100" 
      Height="100"
      Fill="Blue">
      <Rectangle.Triggers>

        <!-- Animates the rectangle's opacity. -->
        <EventTrigger RoutedEvent="Rectangle.Loaded">
          <BeginStoryboard>
            <Storyboard>
              <DoubleAnimation
                Storyboard.TargetName="MyRectangle" 
                Storyboard.TargetProperty="Opacity"
                From="1.0" To="0.0" Duration="0:0:5" 
                AutoReverse="True" RepeatBehavior="Forever" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers>
    </Rectangle>
  </StackPanel>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace SDKSample
{

    public class RectangleOpacityFadeExample : Page
    {
        private Storyboard myStoryboard;

        public RectangleOpacityFadeExample()
        {
            NameScope.SetNameScope(this, new NameScope());

            this.WindowTitle = "Fading Rectangle Example";
            StackPanel myPanel = new StackPanel();
            myPanel.Margin = new Thickness(10);

            Rectangle myRectangle = new Rectangle();
            myRectangle.Name = "myRectangle";
            this.RegisterName(myRectangle.Name, myRectangle);
            myRectangle.Width = 100;
            myRectangle.Height = 100;
            myRectangle.Fill = Brushes.Blue;

            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 1.0;
            myDoubleAnimation.To = 0.0;
            myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
            myDoubleAnimation.AutoReverse = true;
            myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

            myStoryboard = new Storyboard();
            myStoryboard.Children.Add(myDoubleAnimation);
            Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
            Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.OpacityProperty));

            // Use the Loaded event to start the Storyboard.
            myRectangle.Loaded += new RoutedEventHandler(myRectangleLoaded);  

            myPanel.Children.Add(myRectangle);
            this.Content = myPanel;
        }

        public void myRectangleLoaded(object sender, RoutedEventArgs e)
        {
            myStoryboard.Begin(this);
        }

    }
}

Animation Types

Because animations generate property values, different animation types exist for different property types. To animate a property that takes a Double, such as the Width property of an element, use an animation that produces Double values. To animate a property that takes a Point, use an animation that produces Point values, and so on. Because of the number of different property types, there are several animation classes in the System.Windows.Media.Animation namespace. Fortunately, they follow a strict naming convention that makes it easy to differentiate between them:

  • <Type>Animation

    Known as a "From/To/By" or "basic" animation, these animate between a starting and destination value, or by adding an offset value to its starting value.

    • To specify a starting value, set the From property of the animation.

    • To specify an ending value, set the To property of the animation.

    • To specify an offset value, set the By property of the animation.

    The examples in this overview use these animations, because they are the simplest to use. From/To/By animations are described in detail in the From/To/By Animations Overview.

  • <Type>AnimationUsingKeyFrames

    Key frame animations are more powerful than From/To/By animations because you can specify any number of target values and even control their interpolation method. Some types can only be animated with key frame animations. Key frame animations are described in detail in the Key-Frame Animations Overview.

  • <Type>AnimationUsingPath

    Path animations enable you to use a geometric path in order to produce animated values.

  • <Type>AnimationBase

    Abstract class that, when you implement it, animates a <Type> value. This class serves as the base class for <Type>Animation and <Type>AnimationUsingKeyFrames classes. You have to deal directly with these classes only if you want to create your own custom animations. Otherwise, use a <Type>Animation or KeyFrame<Type>Animation.

In most cases, you will want to use the <Type>Animation classes, such as DoubleAnimation and ColorAnimation.

The following table shows several common animation types and some properties with which they are used.

Property type Corresponding basic (From/To/By) animation Corresponding key frame animation Corresponding Path Animation Usage example

Color

ColorAnimation

ColorAnimationUsingKeyFrames

None

Animate the Color of a SolidColorBrush or a GradientStop.

Double

DoubleAnimation

DoubleAnimationUsingKeyFrames

DoubleAnimationUsingPath

Animate the Width of a DockPanel or the Height of a Button.

Point

PointAnimation

PointAnimationUsingKeyFrames

PointAnimationUsingPath

Animate the Center position of an EllipseGeometry.

String

None

StringAnimationUsingKeyFrames

None

Animate the Text of a TextBlock or the Content of a Button.

Animations Are Timelines

All the animation types inherit from the Timeline class; therefore, all animations are specialized types of timelines. A Timeline defines a segment of time. You can specify the timing behaviors of a timeline: its Duration, how many times it is repeated, and even how fast time progresses for it.

Because an animation is a Timeline, it also represents a segment of time. An animation also calculates output values as it progresses though its specified segment of time (or Duration). As the animation progresses, or "plays," it updates the property that it is associated with.

Three frequently used timing properties are Duration, AutoReverse, and RepeatBehavior.

The Duration Property

As previously mentioned, a timeline represents a segment of time. The length of that segment is determined by the Duration of the timeline, which is usually specified by using a TimeSpan value. When a timeline reaches the end of its duration, it has completed an iteration.

An animation uses its Duration property to determine its current value. If you do not specify a Duration value for an animation, it uses 1 second, which is the default.

The following syntax shows a simplified version of the Extensible Application Markup Language (XAML) attribute syntax for the Duration property.

hours : minutes : seconds

The following table shows several Duration settings and their resulting values.


Setting Resulting value

0:0:5.5

5.5 seconds.

0:30:5.5

30 minutes and 5.5 seconds.

1:30:5.5

1 hour, 30 minutes, and 5.5 seconds.

One way to specify a Duration in code is to use the FromSeconds method to create a TimeSpan, the declare a new Duration structure using that TimeSpan.

For more information about Duration values and the complete Extensible Application Markup Language (XAML) syntax, see the Duration type page.

AutoReverse

The AutoReverse property specifies whether a timeline plays backward after it reaches the end of its Duration. If you set this animation property to true, an animation reverses after it reaches the end of its Duration, playing from its ending value back to its starting value. By default, this property is false.

RepeatBehavior

The RepeatBehavior property specifies how many times a timeline plays. By default, timelines have an iteration count of 1.0, which means they play one time and do not repeat at all.

For more information about these properties and others, see the Timing Behaviors Overview.

Applying an Animation to a Property

The previous sections describe the different types of animations and their timing properties. This section shows how to apply the animation to the property that you want to animate. Storyboard objects provide one way to apply animations to properties. A Storyboard is a container timeline that provides targeting information for the animations it contains.

Targeting Objects and Properties

The Storyboard class provides the TargetName and TargetProperty attached properties. By setting these properties on an animation, you tell the animation what to animate. However, before an animation can target an object, the object must usually be given a name.

Assigning a name to a FrameworkElement differs from assigning a name to a Freezable object. Most controls and panels are framework elements; however, most purely graphical objects, such as brushes, transforms, and geometries, are freezable objects. If you are not sure whether a type is a FrameworkElement or a Freezable, refer to the Inheritance Hierarchy section of its type page.

  • To make a FrameworkElement an animation target, you give it a name by setting its Name property. In code, you must also use the RegisterName method to register the element name with the page to which it belongs.

  • To make a Freezable object a target in XAML, you use the x:Name Attribute to assign it a name. In code, you just use the RegisterName method to register the object with the page to which it belongs.

The sections that follow provide an example of naming an element in XAML and code. For more detailed information about naming and targeting, see the Storyboards Overview.

Applying and Starting Storyboards

To start a storyboard in XAML, you associate it with an EventTrigger. An EventTrigger is an object that describes what actions to take when a specified event occurs. One of those actions can be a BeginStoryboard action, which you use to start your storyboard. Event triggers are similar in concept to event handlers because they enable you to describe how your application responds to a particular event. Unlike event handlers, event triggers can be fully described in XAML; no other code is required.

To start a Storyboard in code, you can use an EventTrigger or use the Begin method of the Storyboard class.

Interactively Control a Storyboard

The previous example showed how to start a Storyboard when an event occurs. You can also interactively control a Storyboard after it starts: you can pause, resume, stop, advance it to its fill period, seek, and remove the Storyboard. For more information and an example that shows how to interactively control a Storyboard, see the Storyboards Overview.

What Happens After an Animation Ends?

The FillBehavior property specifies how a timeline behaves when it ends. By default, a timeline starts Filling when it ends. An animation that is Filling holds its final output value.

The DoubleAnimation in the previous example does not end because its RepeatBehavior property is set to Forever. The following example animates a rectangle by using a similar animation. Unlike the previous example, the RepeatBehavior and AutoReverse properties of this animation are left at their default values. Therefore, the animation progresses from 1 to 0 over five seconds and then stops.

<Rectangle
  Name="MyRectangle"
  Width="100" 
  Height="100"
  Fill="Blue">
  <Rectangle.Triggers>

    <!-- Animates the rectangle's opacity. -->
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimation
            Storyboard.TargetName="MyRectangle" 
            Storyboard.TargetProperty="Opacity"
            From="1.0" To="0" Duration="0:0:5" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 1.0;
myDoubleAnimation.To = 0.0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));

Because its FillBehavior was not changed from its default value, which is HoldEnd, the animation holds it final value, 0, when it ends. Therefore, the Opacity of the rectangle remains at 0 after the animation ends. If you set the Opacity of the rectangle to another value, your code appears to have no effect, because the animation is still affecting the Opacity property.

One way to regain control of an animated property in code is to use the BeginAnimation method and specify null for the AnimationTimeline parameter. For more information and an example, see How to: Set a Property After Animating It with a Storyboard.

Note that, although setting a property value that has an Active or Filling animation appears to have no effect, the property value does change. For more information, see the Animation and Timing System Overview.

Data Binding and Animating Animations

Most animation properties can be data bound or animated; for example, you can animate the Duration property of a DoubleAnimation. However, because of the way the timing system works, data bound or animated animations do not behave like other data bound or animated objects. To understand their behavior, it helps to understand what it means to apply an animation to a property.

Refer to the example in the previous section that showed how to animate the Opacity of a rectangle. When the rectangle in the previous example is loaded, its event trigger applies the Storyboard. The timing system creates a copy of the Storyboard and its animation. These copies are frozen (made read-only) and Clock objects are created from them. These clocks do the actual work of animating the targeted properties.

The timing system creates a clock for the DoubleAnimation and applies it to the object and property that is specified by the TargetName and TargetProperty of the DoubleAnimation. In this case, the timing system applies the clock to the Opacity property of the object that is named "MyRectangle."

Although a clock is also created for the Storyboard, the clock is not applied to any properties. Its purpose is to control its child clock, the clock that is created for the DoubleAnimation.

For an animation to reflect data binding or animation changes, its clock must be regenerated. Clocks are not regenerated for you automatically. To make an animation reflect changes, reapply its storyboard by using a BeginStoryboard or the Begin method. When you use either of these methods, the animation restarts. In code, you can use the Seek method to advance the storyboard back to its previous position.

For an example of a data bound animation, see Key Spline Animation Sample. For more information about how the animation and timing system works, see Animation and Timing System Overview.

Other Ways to Animate

The examples in this overview show how to animate by using storyboards. When you use code, you can animate in several other ways. For more information, see the Property Animation Techniques Overview.

Animation Samples

The following samples can help you start adding animation to your applications.

See Also

Reference

Timeline
Storyboard

Concepts

From/To/By Animations Overview
Key-Frame Animations Overview
Storyboards Overview
Timing Behaviors Overview
Animation and Timing System Overview
Timing Events Overview
Get Started Using Windows Presentation Foundation