Navigate back home
GalaSoft Laurent Bugnion
Creating animations in code with Silverlight 1.1 (stand November 2007)

This article is obsolete and remains available for historical reasons only


Introduction

In the current version of Silverlight 1.1, creating animations in code by creating a new Storyboard and one or more new (for example) ColorAnimation(s) is not possible. In WPF, you can do this, but Silverlight doesn't have this ability yet. Thankfully, there is a workaround involving string manipulation and the XamlReader class.

Creating the XAML code

In this example, we will create a ColorAnimation going from one random color to another random color in a random timespan. To keep it simple, we will simply create a new animation when the page is loaded. To see a different animation, you'll need to refresh the page using the F5 key in your web browser.

<Canvas x:Name="parentCanvas" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Loaded="Page_Loaded" x:Class="SilverlightProject1.Page;assembly=ClientBin/SilverlightProject1.dll" Width="640" Height="480"> <Ellipse Width="320" Height="240" Canvas.Top="120" Canvas.Left="160" x:Name="Ellipse" /> </Canvas>
<Canvas.Triggers> <EventTrigger RoutedEvent="Canvas.Loaded"> <BeginStoryboard> <Storyboard Name="TestStoryboard" AutoReverse="True" RepeatBehavior="Forever"> <ColorAnimation Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="(Shape.Fill) .(SolidColorBrush.Color)" From="Red" To="Green" Duration="0:0:2"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Canvas.Triggers>

If you run the code at this point (in Studio, press Ctrl-F5), you'll see the Ellipse's Fill being animated from Red to Green in 2 seconds, and back. The animation never stops, because we set the "RepeatBehavior" property to "Forever".

Passing the animation in code

private const string ANIMATION = "<Storyboard Name=\"TestStoryboard\"" + " AutoReverse=\"True\"" + " RepeatBehavior=\"Forever\">" + "<ColorAnimation Storyboard.TargetName=\"Ellipse\"" + " Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\"" + " From=\"{0}\"" + " To=\"{1}\"" + " Duration=\"{2}\"/>" + "</Storyboard>";

There are a few things you must take care of when you copy XAML code to the C# code file like we just did:

  1. All the attributes quotes must be escaped, by adding a '\' (backslash) character in front of them. This is to signify to the compiler that this quote sign is not a C# string delimiter, but that it must simply be added to the XAML string.
  2. Make sure that there are spaces before the attributes. Even though we placed the string on multiple lines for a better readibility, in the end the string will be all on one line when it is compiled. If you omit to place spaces, this will cause errors. For example, we write " AutoReverse=\"True\"", with a leading space. We could also add new lines instead of putting all on one single line, but this makes the code more difficult to read.
  3. Replace all the elements you want to modify in the code with a "{X}" sequence, where X is a number. All the numbers must be unique. Later, we will use the string.Format method to replace these elements with a random value.

Note: At this stage, you can delete the whole "Canvas.Triggers" section from the XAML code.

Creating random values

The next step is to replace the random values in the animation string. We need three random values: a "From" color, a "To" color and a "Duration". For the "From" and the "To", we will create a new Color from scratch using the Color.FromRgb and Color.ToString methods, using a Random class to create the values:

Random random = new Random(); byte[] rgbFrom = new byte[3]; byte[] rgbTo = new byte[3]; random.NextBytes(rgbFrom); random.NextBytes(rgbTo); Color fromColor = Color.FromRgb(rgbFrom[0], rgbFrom[1], rgbFrom[2]); Color toColor = Color.FromRgb(rgbTo[0], rgbTo[1], rgbTo[2]);

Then we want to construct a Timespan with a random duration, anywhere between 1 and 10 seconds.

TimeSpan duration = TimeSpan.FromSeconds(random.Next(1, 10));

Replacing the values

Eventually, we replace the values in the animation string, then construct the animation object.

string animation = string.Format(ANIMATION, fromColor.ToString(), toColor.ToString(), duration.ToString()); Storyboard storyboard = XamlReader.Load(animation) as Storyboard;

Cleaning up

Before we can start the animation, there are three details we must take care of:

storyboard.Completed += new EventHandler(stoyboard_Completed); storyboard.Begin();

with:

void storyboard_Completed(object sender, EventArgs e) { (sender as Storyboard).Stop(); this.Resources.Remove(sender as DependencyObject); }

Note that alternatively, you can also create the animations in XAML and then modify their properties in code, but that doesn't allow complex code, like animating objects created dynamically at runtime.

Conclusion

Fortunately, the CLR offers enough processing power (compared to JavaScript) to allow even complex animations using string manipulation. Using the objects directly instead of creating XAML strings and using the XamlReader would be faster, but this option doesn't exist in the moment. The technique shown here is a workaround until we get the same possibilities as we have in WPF.

Download

You can download a Visual Studio 2008 project containing the source code.

Demo

Note: You must have Silverlight 1.1 installed to see the demo. Refresh the page to restart the animation with difference values.

Date Version Description
24.11.2008 V1.0.0 First version published