Navigate back home
GalaSoft Laurent Bugnion
WPF: Animations in XAML and code-behind

WPF makes it very easy to define animations, by using timelines, storyboards and dependency properties. Here are a few simple examples and explanations. Additionally, you will find resources to download on the bottom of this article.

For example, let's consider the following TextBlock:

<TextBlock Name="lblHello" Text="Hello world" Margin="0,100,0,0" HorizontalAlignment="Center" FontSize="36" Foreground="White" Cursor="Hand"> <TextBlock.RenderTransform> <RotateTransform Angle="0" CenterX="95" CenterY="20" /> </TextBlock.RenderTransform> </TextBlock>
TextBlock definition

This simply renders the text "Hello world", with a rotation of 0°. Since this is the default anyway, it is not necessary to add the RenderTransform part for this static object. However, since we want to animate this, we need it here. The center point for the rotation is set to 95x20, which is near the top left corner of the letter "w". Note that units in WPF are not pixels, but are device-independant units.

Note also that if you want to define more than one transformation for an object, you must include them in a TransformGroup, which comes between the TextBlock.RenderTransform and the RotateTransform (plus the other tranformations).

Animation triggered in the XAML code

The usual way to start animations in XAML is by using triggers. There are many types of triggers, and enumerating them goes beyond the scope of this post. In this example, we will start the animation when the user clicks on the label. Refer to the documentation to find the exhaustive list of events.

<Page.Triggers> <EventTrigger RoutedEvent="TextBlock.MouseDown" SourceName="lblHello"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="lblHello" Storyboard.TargetProperty="(TextBlock.RenderTransform).(RotateTransform.Angle)" From="0" To="360" Duration="0:0:0.5" RepeatBehavior="4x" /> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Page.Triggers>
Animation triggered by a click

What did we do here? It looks a bit complicated, but in fact this code can be read like a text: We define an Event Trigger, happening when the user clicks the mouse in the TextBox. The action defined is to begin a storyboard, which contains an animation of type double (in WPF, the animation's type depends on the type of the dependency property we want to animate. In our case, the rotation angle is of type double, so we use a DoubleAnimation).

The animation itself is not too difficult to understand either:

  • We define the target object of the animation, which is our label lblHello.
  • The dependency property to animate is more difficult to find, I'll come to this later.
  • We define the start and end values of the property animation with the From and To attributes (there is also a "By" attribute, which allows to define by how much the value of the property must change during the animation).
  • The duration is expressed with the syntax "hh:mm:ss,ff" where ff are fractions of seconds.
  • The number of times that the animation must run is defined with the "RepeatBehavior" attribute. There are different syntaxes for this attribute, for example: "0:0:4" specifies that the animation must run only for 4 seconds, whatever else is defined. Another choice is "Forever" which is self explaining. In our case, we specify "4x" which means 4 times.

To sum up, this animation will act on the angle, changing it from 0 to 360 degrees in 0.5 seconds, and will be repeated 4 times. So the whole duration will be 2 seconds.

Note that it is also possible to use the BeginTime property of the animation object to delay an animation, for example in order to cascade animations. Another way is to use the Completed event, which can be set in the XAML code, or in the code-behind. This event implies that the corresponding method must be present in the code-behind, thus it is not applicable for pure XAML applications.

Finding the path to the property to animate is in my experience the most difficult thing when you define an animation, because there is no support (intellisense, error handling) to guide you. In our case it's not that bad, because the animation is simple (only a rotation). If you define a complex animation with a "TransformGroup", then finding the right path is more difficult. Two things to remember:

  1. The TargetProperty refers to the Class, not to the object. In our case, it refers to "TextBlock.RenderTransform", not to "lblHello.RenderTransform" (that would be wrong).
  2. Use parenthesis to group the expressions. For example, (TextBlock.RenderTransform).

In my opinion, the best way to find the right path is to look at examples and to understand how they work, and then to try and fail until you try and succeed!

It's worth mentioning that there are a *lot* of properties that you can animate. For example, you can use the Opacity to make a fade-in / fade-out effect. Or, you can specify a start and an end colors, and then have an animation transitioning from one to the other. The possibilities are limited only by imagination!

Triggering animations in code-behind

Sometimes, the events exposed in XAML are just not enough. For example, if you want to start an animation when a certain method is called, you must resort to the code-behind. This is when resources come handy.

In XAML, you can define styles, animations, etc... but instead of applying them to an object, you just store them in a storage area called resources. For example, the "stored" animation here above becomes:

<Page.Resources> <Storyboard x:Key="sbdLabelRotation"> <DoubleAnimation Storyboard.TargetName="lblHello" Storyboard.TargetProperty="(TextBlock.RenderTransform).(RotateTransform.Angle)" From="0" To="360" Duration="0:0:0.5" RepeatBehavior="4x" /> </Storyboard> </Page.Resources>
Animation stored in resources

Note that the storyboard is identified by a key, which allows to retrieve it in the code-behind. It's then possible to use the Storyboard class and its Begin method to trigger the animation "manually".

public void AnimateLabelRotation( object sender, RoutedEventArgs e ) { Storyboard sbdLabelRotation = (Storyboard) FindResource( "sbdLabelRotation" ); sbdLabelRotation.Begin( this ); }
Triggering the animation in the code-behind
Defining animations in the code-behind

Animations can also be written in C#, which becomes handy when you don't have a XAML front-end. For example, if you create a WPF custom control, there is no XAML involved. If I had to judge, I would say that animations are easier to define in XAML than in C#, especially complex animations acting on TransformGroups.

Here is however the same animation, this time in C#: Note the use of a Timespan to specify the animation duration. Note also that because there is only one transformation, accessing it is quite straightforward: simply cast the TextBlock.RenderTransform property to a RotateTransform.

public void AnimateLabelRotationInCode( object sender, RoutedEventArgs e ) { DoubleAnimation oLabelAngleAnimation = new DoubleAnimation(); oLabelAngleAnimation.From = 0; oLabelAngleAnimation.To = 360; oLabelAngleAnimation.Duration = new Duration( new TimeSpan( 0, 0, 0, 0, 500 ) ); oLabelAngleAnimation.RepeatBehavior = new RepeatBehavior( 4 ); RotateTransform oTransform = (RotateTransform) lblHello.RenderTransform; oTransform.BeginAnimation( RotateTransform.AngleProperty, oLabelAngleAnimation ); }
Animation fully defined in code-behind
Conclusion

In this tutorial, we saw how to get started with WPF animations in XAML and also in C#. Animations are crucial in WPF, because of the dynamism that they add to the user interface. There are many types of animations, including 3D, but everyone has to start somewhere. I hope that these examples will help the reader to build knowledge and to extend it in order to create complex animations.

Resources