Manipulating Storyboards at Runtime with Silverlight 1.1

January 31, 2008
No Comments.

Url: http://wilderminds.blob.core.windows.net/downloads/manipulatestory…
Silverlight
In response to a question posed on Silverlight.net’s forums I crufted up a quick example of how to modify a Storyboard at runtime with Silverlight 1.1 (soon to be 2.0). The question was about both modifying the values of individual keyframes of but also changing the Storyboard’s TargetName. Its driven by the ability to re-use Storyboards/Animations for multiple XAML elements.

I started with some simple XAML…three images placed near the top of the page. I want to have a storyboard with two animations; one for Canvas.Left and one for Canvas.Top. Here’s the XAML I used:

...
<Canvas.Resources>
  <Storyboard x:Name="theMover" Storyboard.TargetName="Image1">
    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" 
                     Storyboard.TargetProperty="(Canvas.Left)">
      <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
      <SplineDoubleKeyFrame KeyTime="00:00:02" Value="386"/>
    </DoubleAnimationUsingKeyFrames>
    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" 
                     Storyboard.TargetProperty="(Canvas.Top)">
      <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
      <SplineDoubleKeyFrame KeyTime="00:00:02" Value="127"/>
    </DoubleAnimationUsingKeyFrames>
  </Storyboard>
</Canvas.Resources>
<Image x:Name="Image1" Source="sllogo.jpg" 
       Canvas.Top="8" Canvas.Left="8" />
<Image x:Name="Image2" Source="headshot.jpg" 
       Canvas.Left="154" Canvas.Top="8" />
<Image x:Name="Image3" Source="aglicense.jpg" 
       Canvas.Left="380" Canvas.Top="8" />
...

Now I wanted to have a handler in the code that when I clicked on a button to switch the animation between the three images and set the values of the storyboard.  First I setup an array of the Images so I can switch between them simply:

Image[] _images;
int _currentImage = 0;
Random _rnd = new Random();

public void Page_Loaded(object o, EventArgs e)
{
  // Required to initialize variables
  InitializeComponent();

  theButton.MouseLeftButtonUp += 
    new MouseEventHandler(theButton_MouseLeftButtonUp);

  _images = new Image[] { Image1, Image2, Image3 };
}

Next I handle the Mouse event and modify the Storyboard and kick it off:

void theButton_MouseLeftButtonUp(object sender, MouseEventArgs e)
{
  // Stop the Storyboard (to ensure its stopped)
  // We can't change anything while its running
  theMover.Stop();

  // Set the TargetName
  theMover.SetValue<string>(Storyboard.TargetNameProperty, 
                            _images[_currentImage].Name);

  // Set random Values for the Canvas.Left Animation
  DoubleAnimationUsingKeyFrames leftAnimation = 
       (DoubleAnimationUsingKeyFrames)theMover.Children[0];
  leftAnimation.KeyFrames[0].Value = _rnd.Next(400);
  leftAnimation.KeyFrames[1].Value = _rnd.Next(400);
  
  // Set random Values for the Canvas.Left Animation
  DoubleAnimationUsingKeyFrames topAnimation = 
       (DoubleAnimationUsingKeyFrames)theMover.Children[1];
  topAnimation.KeyFrames[0].Value = _rnd.Next(400);
  topAnimation.KeyFrames[1].Value = _rnd.Next(400);

  // Start the Animation
  theMover.Begin();

  // Change the counter so it picks the next image next time
  if (_currentImage < 2) _currentImage++;
  else _currentImage = 0;
}

It isn’t elegant, but it does work so if you want to re-use a Storyboard grab the sample and get going!