I’ve discussed how to locate the UIElement associated with an
animation’s Completed
event a while back for WPF.
Here’s an update for how I do the same thing in Silverlight 2.0. The technique
could be used in WPF with a few minor tweaks. I like this method rather than relying
on a Storyboard (as I have better control over the completion of individual
animations this way).
Here’s
a page on MSDN that describes various ways to work with animations programmatically
in Silverlight.
The
Completed
event is raised when the animation timeline has ended. The event unfortunately
passes only a reference to the sender (which is the Timeline). The EventArgs is
empty.
Here’s a chunk of code that sets up an animation programmatically:
BitmapImage bmimg = sender as BitmapImage;
Game.Dispatcher.BeginInvoke(delegate()
{
DoubleAnimation animation = new DoubleAnimation();
animation.To = 0.0;
animation.From = 1.0;
animation.Duration = new Duration(TimeSpan.FromSeconds(2 + Game.Randomizer.Next(5)));
animation.SetValue(Page.ImageProperty, bmimg);
animation.Completed += new EventHandler(animation_Completed);
Image img = bmimg.GetValue(Page.ImageProperty) as Image;
Storyboard sb = new Storyboard();
sb.Children.Add(animation);
Storyboard.SetTarget(animation, img);
Storyboard.SetTargetProperty(animation, new PropertyPath("Opacity"));
sb.Begin();
});
}
The significant line above is the animation SetValue. Here, I’m using the
power of the Dependency Object. I can attach new properties to the animation
directly!
public static readonly DependencyProperty ImageProperty =
DependencyProperty.RegisterAttached("Image", typeof(DependencyObject), typeof(Page), null);
I’ve created a new DependencyProperty (as an attached property) called
ImageProperty. There’s not much meaning to the name — other than it
makes sense in the context in which I’m using it in the larger application.
void animation_Completed(object sender, EventArgs e)
{
Timeline t = sender as Timeline;
if (t != null)
{
BitmapImage img = t.GetValue(Page.ImageProperty) as BitmapImage;
if (img != null)
{
// do something here...
}
}
}
In the completed event, I retrieve the attached property’s value from the
animation (which I’ve cast to one of the base types, a
Timeline). Then, you could do whatever you want….