Animations in Windows Presentation Foundation

by Keyvan Nayyeri
Summary
In the fourth article of our series about UniveRSS we discuss animations in XAML and Windows Presentation Foundation because animations are a main part of the UniveRSS user interface and an important part of WPF as well as being one of its powerful features.

In this article we walk through the principles of animations in WPF and talk about StoryBoard, RepeatBehavior, Transformation, ParallelTimeLine and KeyFrame.
Introduction
Animations are one of most important aspects of Windows Presentation Foundation and they make a powerful part of this new technology in .NET Framework 3.0. Creating an animation in preceding graphic engines was a time-consuming process but in WPF things are simpler and you can build animations easily. Animations are a built-in part of XAML as markup language for declaring user interfaces in WPF and several options are available to build animations.
UniveRSS as a 3D RSS reader specifically designed for .NET 3.0 with WPF comes with animations at the heart of its user interface. Feeds are presented in constantly rotating cubes suspended in a virtual universe. These 3D animations are a main part of the UniveRSS application so we decided to dedicate an article to animations in Windows Presentation Foundation to show the principles of animations in these new technologies.
In this article we want to talk about animations in XAML and WPF. First we begin with a background then will talk about StoryBoards, different animation types, RepeatBehavior, Transformations, ParallelTimeLine and KeyFrames.
Background
Timing is crucial in building animations. Timing is the process to calculate times for each frame in an animation, when it starts, when it ends and total time of an animation. In older graphic engines timing was a little hard to accomplish but in WPF massively simplified, with the WPF engine doing the job for you.

Usually an animation consists of changing a color or an angle or width and height of a control or transforming a shape or control. WPF supports all these animation types out of the box. You can create your animations based on different events on a WPF UI. You build your animations using RoutedEvents and triggers. You should use StoryBoard elements to declare your animations. Each StoryBoard may contain one or more basic animation types. Later in this article you’ll read about StoryBoards and other elements that play a role in animations.
StoryBoards
StoryBoard is the core element of animations. StoryBoards must be nested inside a BeginStoryBoard element inside event triggers. Each StoryBoard consists of one or more basic animation types to animate a control. This element comes with two important properties: StoryBoard.TargetName and StoryBoard.TargetProperty. Storyboard specifies the name of the element that should be animated and TargetName specifies the property of the element that should be animated by StoryBoard. StoryBoard.TargetProperty must be set to the correct property based on the hierarchy of elements, sub-elements and attributes in XAML.

Inside the StoryBoard you can put one or more basic animation types based on the animation that you want to build. Generally all basic animation types share the following important properties:
  • From: Initial value of property when animation begins.
  • To: Last value of property when animation ends.
  • By: Intermediate value of property at the middle of animation. It’s a bridge between From and To. This property is optional.
  • Duration: Total time of animation.
  • RepeatBehavior: Behavior of animation. You’ll read about this property later.
Listing 1 is an example of StoryBoards in action. In the script the background color of a Button is animated from Pink to Blue and then to Green in 6 seconds whenever the user moves the mouse over the button.
Listing 1
<Window x:Class="UniveRSS.Animations.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Animations in WPF" Height="300" Width="300">
  <Grid>
   <Grid.Triggers>
    <EventTriggerRoutedEvent="Rectangle.MouseEnter">
     <EventTrigger.Actions>
      <BeginStoryboard>
        <Storyboard Storyboard.TargetName="myButton"
        Storyboard.TargetProperty="(Background).
        (SolidColorBrush.Color)">
          <ColorAnimation From="Pink"
			To="Green"
			By="Blue"
			Duration="0:0:6" />
        </Storyboard>
       </BeginStoryboard>
      </EventTrigger.Actions>
     </EventTrigger>
   </Grid.Triggers>
    <Button Name="myButton"
    Width="150"
    Height="35"
    Background="Pink">
    Click Me!
    </Button>
  </Grid>
</Window>

For ease of demonstration, the animation image in Figure 1 is shown to run unlimited iterations.
Figure 1
Animation Figure 1
Repeat Behaviour
Using two properties you can change the behavior of your animations in two ways. You can reverse the animation by setting the AutoReverse property of each animation type to true.

You may also set RepeatBehavior of each animation type in order to manage the number of iterations for each animation. You can set this property to Forever to force your animation to run forever (until you stop the application). You can also set it to different numbers of iterations to force it to iterate for the desired number of times.

Listing 2 is the reverse animation of Listing 1 that runs for three times.
Listing 2
<Window x:Class="UniveRSS.Animations.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Animations in WPF" Height="300" Width="300">
  <Grid>
    <Grid.Triggers>
      <EventTrigger RoutedEvent="Rectangle.MouseEnter">
        <EventTrigger.Actions>
          <BeginStoryboard>
            <Storyboard Storyboard.TargetName="myButton"
            Storyboard.TargetProperty="(Background).
            (SolidColorBrush.Color)">
              <ColorAnimation From="Pink"
                              To="Green"
                              By="Blue"
                              Duration="0:0:6"
                              RepeatBehavior="3x"
                              AutoReverse="True" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger.Actions>
      </EventTrigger>
    </Grid.Triggers>
    <Button Name="myButton"
     Width="150"
     Height="35"
     Background="Pink">
      Click Me!
    </Button>
  </Grid>
</Window>

Output is shown as a .gif file in Figure 2.
Figure 4
Animation Figure 2
Transformations
Transformations are another way to animate controls. Using transformations you can change the angle of each control which is a common way to animate objects in user interfaces. To make transformations possible, you have to use one DoubleAnimation to change the RenderTransform of an object when an event occurs. For example in Listing 3 I used transformations to change the angle of RotateTransform to transform a button from 0 to 180 degrees in 6 seconds.
Listing 3
<Window x:Class="UniveRSS.Animations.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Animations in WPF" Height="300" Width="300">
  <Grid>
    <Grid.Triggers>
      <EventTrigger RoutedEvent="Rectangle.MouseEnter">
        <EventTrigger.Actions>
          <BeginStoryboard>
            <Storyboard Storyboard.TargetName="myButton"
            Storyboard.TargetProperty="(RenderTransform).
            (RotateTransform.Angle)">
              <DoubleAnimation From="0"
                              To="180"
                              By="90"
                              Duration="0:0:6"
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger.Actions>
      </EventTrigger>
    </Grid.Triggers>
    <Button Name="myButton"
     Width="150"
     Height="35"
     Background="Pink">
      Click Me!
    </Button>
  </Grid>
</Window>

You can see the output in Figure 3
Figure 3
Animation Figure 3
ParallelTimeLine
Sometimes you need to create two or more animations that run in parallel. This is very easy to accomplish in Windows Presentation Foundation. All you need to do is nest your StoryBoards inside a ParallelTimeLine element within a parent StoryBoard. This way, all those StoryBoards and their animations will run in parallel. Listing 4 is an example of ParallelTimeLine where I animate a button to change its background color while its RenderTransform angle is changing from 0 to 180 degrees (In actual fact, I merged two animations that are provided in Listing 1 and Listing 3).
Listing 4
<Window x:Class="UniveRSS.Animations.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Animations in WPF" Height="300" Width="300">
 <Grid>
  <Grid.Triggers>
   <EventTrigger RoutedEvent="Rectangle.MouseEnter">
    <EventTrigger.Actions>
     <BeginStoryboard>
      <Storyboard>
       <ParallelTimeline>
        <Storyboard Storyboard.TargetName="myButton"
         Storyboard.TargetProperty="(Background).
         (SolidColorBrush.Color)">
          <ColorAnimation From="Pink"
			To="Green"
			By="Blue"
			Duration="0:0:6" />
           </Storyboard>
           <Storyboard Storyboard.TargetName="myButton"
           Storyboard.TargetProperty="(RenderTransform).
           (RotateTransform.Angle)">
            <DoubleAnimationFrom="0"
			To="180"
			By="90"
			Duration="0:0:6" />
          </Storyboard>
         </ParallelTimeline>
        </Storyboard>
       </BeginStoryboard>
      </EventTrigger.Actions>
     </EventTrigger>
    </Grid.Triggers>
   <Button Name="myButton"
	Width="150"
	Height="35"
	Background="Pink">
   <Button.RenderTransform>
     <RotateTransform Angle="0"CenterX="105"CenterY="30" />
   </Button.RenderTransform>
      Click Me!
    </Button>
   </Grid>
  </Window>


Output is shows in Figure 4 as unlimited iterations.
Figure 4
Animation Figure 4
KeyFrame
By default all built-in animation types use a symmetric way to animate elements and divide total time into equal frames but sometimes you need to manage the length of time that each frame of animation appears in output. In this case you can declare different values for different frames by using different types of KeyFrames. Each basic animation type has a corresponding KeyFrame to let you declare KeyFrames for that type. For example in Listing 5 I use LinearDoubleKeyFrames to change the Width of a button from 60 to 120 with different values on each time frame.
Listing 5
<Window x:Class="UniveRSS.Animations.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Animations in WPF" Height="300" Width="300">
 <Grid>
   <Grid.Triggers>
     <EventTrigger RoutedEvent="Rectangle.MouseEnter">
       <EventTrigger.Actions>
         <BeginStoryboard>
           <Storyboard Storyboard.TargetName="myButton"
             Storyboard.TargetProperty="Width">
              <DoubleAnimationUsingKeyFrames Duration="0:0:8">
              <LinearDoubleKeyFrame KeyTime="0:0:2" Value="60"/>
              <LinearDoubleKeyFrame KeyTime="0:0:4" Value="80"/>
              <LinearDoubleKeyFrame KeyTime="0:0:6" Value="100"/>
              <LinearDoubleKeyFrame KeyTime="0:0:8" Value="120"/>
              </DoubleAnimationUsingKeyFrames>
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger.Actions>
      </EventTrigger>
    </Grid.Triggers>
    <Button Name="myButton"
     Width="60"
     Height="35"
     Background="Pink">
      Click Me!
    </Button>
  </Grid>
</Window>

Figure 5 shows the result as unlimited iterations.
Figure 5
Animation Figure 5
How it is done in UniveRSS
3D effects and animations differ in WPF and are slightly more complicated than 2D effects. 3D animations need some calculations in order to have the right values for animation elements and attributes.

In our showcase, UniveRSS, all animations are done frame by frame explicitly using built-in 3D animation features from the Windows Presentation Foundation. In later articles 3D animations will be described in greater detail.
Keyvan Nayyeri has been a geek and programmer since he was 10. He has a BS degree in Applied Mathematics and as an experienced software architect and developer he is also a MVP from Telligent for Community Server technology. Keyvan is a co-author for Wrox press and also an author for ASP Alliance, DotNetSlackers and Code Project .NET communities. Currently he’s contributed in some projects such as BlogML, CSModules and Windows Live Writer Plugins. He edits his blog on .NET, Community Server and Technology.
The showcases on the Panel website provide examples of the possibilities within the new technologies and source codes serving as a blueprint for beginners learning to leverage these technologies. The development of the UniveRSS feed reader and other showcases on the Panel website are accompanied by articles with detailed information on the projects' underlying technologies.

The following topics are featured in this series of articles:
  • An introduction to UniveRSS, Windows Presentation Foundation, XAML and Internet Explorer 7 platform.
  • General architecture of UniveRSS and step by step guide of its development details.
  • An overview of the Windows RSS Platform
  • The use of animations in WPF
  • An overview of the UniveRSS Architecture
You can subscribe to your local MSDN Flash newsletter using the Panel registration to get notifications of new articles.
© 2007 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement