Silverlight 1.1 Storyboards and Managed Code
Animations in Silverlight are dead easy. With a small amount of XAML you are easily able to make your application look amazing and show off your design skills. In some cases however, you want to step out of the XAML and into the world of managed C# and create some dynamic animations.
As an example in an application I'm currently busy with, I needed to dynamically create an animation on a Framework to create a snapping effect when dragging the element on the screen. This can easily be done in managed code by creating a StoryBoard object and adding DoubleAnimation objects to this storyboard. However, in the current release of Silverlight 1.1, creating animations using code causes runtime errors because of an inconvenient bug.
The work around is surprisingly easy. How do we do it? Simply create the animation as you would have done in XAML and load it into an object. Have a look below:
1: string storyboardName = "MyStoryBoard";
2: string myXamlElement = "MyXamlElement";
3:
4: int newLeftPosition = 120;
5:
6: Storyboard sb = XamlReader.Load(String.Format(
7: @"<Storyboard xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" x:Name=""{0}""> 8: <DoubleAnimation Storyboard.TargetName=""{1}"" 9: Storyboard.TargetProperty=""(Canvas.Left)""
10: To=""{2}"" Duration=""00:00:00.1200000""/> 11: </Storyboard>", storyboardName, myXamlElement , newLeftPosition )) as Storyboard;
12:
13: //Add a delegate to remove the storyboard from resources as soon as it is finished.
14: sb.Completed += delegate(object sender, EventArgs eventArgs)
15: { 16: this.Resources.Remove(sb);
17: };
18:
19: //Add to the resources of the page
20: this.Resources.Add(sb);
21:
22: //Begin the storyboard which will animate the element to the correct position.
23: sb.Begin();
The XamlReader object has a wonderful static method called Load() which takes in a string and returns a DependancyObject object which you can then cast to the StoryBoard element we know it is.
As you can see, this animation moves a target element to a new Canvas.Top position based on the number we pass into newLeftPosition. Because this is a dynamic resource, we don't want old animations hanging around in the resource dictionary. Luckily for us, we have a Completed event to hook into which as you can see on line 12, we remove the animation from the resources collection by using an inline delegate.
Not very elegant, but does solve our problem. Pretty nifty stuff!