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
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 your classes can inherit, to produce customized animations. These custom animations gain many of the performance benefits of the standard animation classes.
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.
There must be a compatible animation type available. (If WPF does not provide one, you can create your own. See the Custom Animations Overview.)
WPF contains many objects that have IAnimatable 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 part of the user interface if they meet the criteria that are described in this section.
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.
Dim myPanel As StackPanel = New StackPanel myPanel.Margin = New Thickness(10) Dim myRectangle As Rectangle = New Rectangle myRectangle.Name = "myRectangle" Me.RegisterName(myRectangle.Name, myRectangle) myRectangle.Width = 100 myRectangle.Height = 100 myRectangle.Fill = Brushes.Blue myPanel.Children.Add(myRectangle) Me.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.
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. The following shows how to create a DoubleAnimation in XAML.
The following shows how to create a DoubleAnimation in code.
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. The following shows how to set the Duration to five seconds in XAML.
The following shows how to set the Duration to five seconds in code.
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.The following shows how to set the AutoReverse and RepeatBehavior properties in XAML.
Part 2: Create a Storyboard
Then initialize the Storyboard and add the animation as its child.
The Storyboard has to know where to apply the animation. Use the Storyboard.TargetName attached property to specify the object to animate. The following shows how to set the target name of the DoubleAnimation to MyRectangle in XAML.
The following shows how to set the target name of the DoubleAnimation to MyRectangle in code.
Part 3 (XAML): Associate the Storyboard with a Trigger
Create an EventTrigger and add the BeginStoryboard to its Actions collection. Set the RoutedEvent property of the EventTrigger to the routed event that you want to start the Storyboard. (For more information about routed events, see the Routed Events Overview.)
<!-- 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 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 following shows how to create a rectangle that fades in and out of view in XAML.
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <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> </Grid> </Window>
The following shows how to create a rectangle that fades in and out of view in code.
Imports System.Windows.Media.Animation Class MainWindow Private myStoryboard As Storyboard Public Sub New() InitializeComponent() Dim myPanel As New StackPanel() myPanel.Margin = New Thickness(10) Dim myRectangle As New Rectangle() myRectangle.Name = "myRectangle" Me.RegisterName(myRectangle.Name, myRectangle) myRectangle.Width = 100 myRectangle.Height = 100 myRectangle.Fill = Brushes.Blue Dim myDoubleAnimation As 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. AddHandler myRectangle.Loaded, AddressOf myRectangleLoaded myPanel.Children.Add(myRectangle) Me.Content = myPanel End Sub Private Sub myRectangleLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs) myStoryboard.Begin(Me) End Sub End Class
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:
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.
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.
Path animations enable you to use a geometric path in order to produce animated values.
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.
The following table shows several common animation types and some properties with which they are used.
Corresponding basic (From/To/By) animation
Corresponding key frame animation
Corresponding Path Animation
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.
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.
The following syntax shows a simplified version of the Extensible Application Markup Language (XAML) attribute syntax for the Duration property.
The following table shows several Duration settings and their resulting values.
30 minutes and 5.5 seconds.
1 hour, 30 minutes, and 5.5 seconds.
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.
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 reference documentation.
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 an animation target in XAML, you use the x:Name Directive 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 specify how your application responds to a particular event. Unlike event handlers, event triggers can be fully described in XAML; no other code is required.
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.
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>
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.
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."
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 shift the storyboard back to its previous position.
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.
The following samples can help you start adding animation to your applications.
Lists helpful tips for solving issues with animations, such as performance.
Describes how to extend the animation system with key frames, animation classes, or per-frame callbacks.
Describes how to create an animation that transitions between two values.
Describes how to create an animation with multiple target values, including the ability to control the interpolation method.
Explains how to apply mathematical formulas to your animations to get realistic behavior, such as bouncing.
Describes how to move or rotate an object along a complex path.
Describes property animations using storyboards, local animations, clocks, and per-frame animations.
Describes how to use storyboards with multiple timelines to create complex animations.
Describes the Timeline types and properties used in animations.
Contains code examples for using animations and timelines in your application.
Contains code examples for using the Clock object in your application.
Contains code examples for using key-frame animations in your application.
Contains code examples for using path animations in your application.