Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Web Development

Dynamic Storyboards and Animations in Silverlight 2


Dan Wahlin (Microsoft Most Valuable Professional for ASP.NET and XML Web Services) is a .NET development instructor and architecture consultant at Interface Technical Training. Dan founded the XML for ASP.NET Developers site, which focuses on using ASP.NET, XML, Silverlight, AJAX, and Web Services on .NET. Dan has co-authored/authored several different books on .NET, including ASP.NET 2.0 MVP Hacks, Professional ASP.NET AJAX, XML for ASP.NET Developers and is currently working on a new book on Silverlight 2. Dan blogs at http://weblogs.asp.net/dwahlin.


Animations are a key part of Silverlight 2 that allow your applications to stand out from all of the boring and dull applications floating around on the Web. In previous articles I’ve written about storyboards and animations but as a quick review, Silverlight relies upon a Storyboard element to define several different types of animations such as DoubleAnimation (which animates object properties of type double) and ColorAnimation (which animates color properties). In this article I show you how Silverlight can be used to create animations programmatically and how you can interact with animations defined declaratively in a XAML file using C#.

For this example I create a simple "lightbox" style container that can display pictures from Flickr. As the picture is being shown the box will grow from a height/width of 0 to a larger size that’s determined by the size of the browser. Three different animations will be performed by the image display container:

  • Animate the Width from 0 to the width of the browser / 1.5
  • Animate the Height from 0 to the height of the browser / 1.5
  • Animate the Opacity from 0 to 1

If you know the To and From values of the animations upfront then it’s easiest to define them in the XAML file. In cases where there’s an unknown animation property value, you can create the storyboard and animation objects programmatically or update properties of an existing Storyboard defined in XAML. In this case a Border control will be animated:


<Border x:Name="LightBoxControl" BorderBrush="Black" BorderThickness="3" 
        CornerRadius="10"  
        Height="20" Width="20" Opacity="0" Margin="5" 
        MouseLeftButtonDown="Image_MouseLeftButtonDown">
    <Border.Background>
        <LinearGradientBrush EndPoint="0.893,0.116" 
           StartPoint="0.403,0.694">
            <GradientStop Color="#FFB9B9B9" Offset="1"/>
            <GradientStop Color="#FF4F4F4F" Offset="0"/>
            <GradientStop Color="#FF666666" Offset="0.496"/>
        </LinearGradientBrush>
    </Border.Background>
    <StackPanel x:Name="spImage">
        <Border HorizontalAlignment="Right" VerticalAlignment="Top" 
         BorderBrush="Black" BorderThickness="1" CornerRadius="8" 
         Background="LightGray" Width="60" Height="25">
            <TextBlock HorizontalAlignment="Center" 
             VerticalAlignment="Center" FontSize="12" Text="Close" />
        </Border>
        <Rectangle x:Name="LightBoxImage" HorizontalAlignment="Center" 
                   Fill="Black" RadiusX="10" RadiusY="10" 
                   Stroke="LightGray" StrokeThickness="2" Margin="5">
        </Rectangle>
    </StackPanel>
</Border>

Here’s an example of programmatically creating a Storyboard and defining the three animations mentioned earlier to change the Width, Height and Opacity properties of the Border control:


double? width = (double?)System.Windows.Browser.HtmlPage.Document.Body.GetProperty(
  "offsetWidth") / 1.5;
double? height = (double?)System.Windows.Browser.HtmlPage.Document.Body.GetProperty(  "offsetHeight") / 1.5;
//Programmatic way to create a storyboard and animations
Storyboard sb = new Storyboard();

//Create animation for Border control's Width
DoubleAnimation wa = new DoubleAnimation();
wa.Duration = new Duration(TimeSpan.FromSeconds(0.5))
wa.From = 0;
wa.To = width;
Storyboard.SetTarget(wa, LightBoxControl);
Storyboard.SetTargetProperty(wa, new PropertyPath(Border.WidthProperty));
sb.Children.Add(wa);

//Create animation for Border control's Height
DoubleAnimation ha = new DoubleAnimation();
ha.Duration = new Duration(TimeSpan.FromSeconds(0.5));
ha.From = 0;
ha.To = height;
Storyboard.SetTarget(ha, LightBoxControl);
Storyboard.SetTargetProperty(ha, new PropertyPath(Border.HeightProperty));
sb.Children.Add(ha);

//Create animation for Border control's Opacity
DoubleAnimation oa = new DoubleAnimation();
oa.Duration = new Duration(TimeSpan.FromSeconds(0.5));
oa.From = 0;
oa.To = 1;
Storyboard.SetTarget(oa, LightBoxControl);
Storyboard.SetTargetProperty(oa, new PropertyPath(Border.OpacityProperty));
sb.Children.Add(oa);

this.spImage.Width = width.Value - 30;
this.spImage.Height = height.Value - 30;
this.LightBoxImage.Width = width.Value - 75;
this.LightBoxImage.Height = height.Value - 75;
sb.Begin();

In this example the final height and width of the target Border control are determined by grabbing the offsetWidth and offsetHeight values using the HtmlPage class. Once those values are determined a Storyboard object is created along with the three animations all of type DoubleAnimation. Each animation takes 1/2 second to complete and animates the Border control’s Height, Width, and Opacity properties respectively.

Looking through the code for each animation object you’ll notice that it is associated with the target object and target object property using the Storyboard.SetTarget() and Storyboard.SetTargetProperty() static methods respectively. This may seem strange at first glance but makes sense once you understand the concept of attached properties. Each animation object is added to the parent Storyboard object using the Children.Add() method and the Storyboard is started by calling the Begin() method.

Interacting with Storyboards and Animations Defined in XAML

The programmatic approach to creating animations works great when there’s a lot of dynamic data being fed into animation objects. However, in this example only the Height and Width properties are being changed on the Border control. That’s a lot of code to write to change two properties. Rather than defining everything programmatically you can instead define the storyboard and associated animations declaratively and fill in the dynamic pieces at runtime. Here’s an example of defining the three animations shown earlier in XAML:


<Storyboard x:Name="sbShow">
    <DoubleAnimation x:Name="daWidth" 
                     Storyboard.TargetName="LightBoxControl"
                     Storyboard.TargetProperty="Width"
                     From="0" Duration="00:00:0.5" />
    <DoubleAnimation x:Name="daHeight" 
                     Storyboard.TargetName="LightBoxControl"
                     Storyboard.TargetProperty="Height"
                     From="0" Duration="00:00:0.5" />
    <DoubleAnimation Storyboard.TargetName="LightBoxControl"
                     Storyboard.TargetProperty="Opacity"
                     From="0" To="1" Duration="00:00:0.5" />
</Storyboard>

Before the storyboard starts to play the To property of the daWidth and daHeight objects can then be assigned values as shown next:


double? width = (double?)System.Windows.Browser.HtmlPage.Document.Body.GetProperty(
  "offsetWidth") / 1.5;
double? height = (double?)System.Windows.Browser.HtmlPage.Document.Body.GetProperty(
  "offsetHeight") / 1.5;

//Define how big the Border control should be animated to by setting the To property value

this.daWidth.To = width;
this.daHeight.To = height;

this.spImage.Width = width.Value - 30;
this.spImage.Height = height.Value - 30;
this.LightBoxImage.Width = width.Value - 75;
this.LightBoxImage.Height = height.Value - 75;

this.sbShow.Begin();

And that’s all there is to it! Silverlight makes it easy to work with dynamic animations whether programmatically or through modifying storyboards defined in XAML. Download a working version of the Flickr lightbox application here if you’d like to see the animations in action (as well as some others).


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.