I have fallen deeply in love with Silverlight and it's evident, in Silverlight 2 at least, that one cannot do everything in XAML and there is still an element of code needed to do a job.
Because of the lack of triggers in the same sense as those that exist in WPF, Silverlight can be a pain when we need to create dynamic animated effects. However I had an idea that leans heavily upon the joys of garbage collection and anonymous methods to provide a fire-and-forget style storyboard which can do animations and handle its own events.
One little job I recently accomplished with this was to create some animation effects that had two stages; for example, to fade one element out and replace it with another.
The joy of this technique is that we can build a storyboard and the associated animation details dynamically, set it running and then just forget it while it does its thing. After the events have fired the whole thing -should- be reclaimed and garbage collected. (He said, wondering about shooting himself in the foot.
Here's some XAML...
<UserControl x:Class="FireAndForget.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Ellipse Fill="red"/>
<Button Content="Click Me" Width="100" Height="25" Click="Button_Click"/>
Grid>
UserControl>
And here’s the button click code..
private void Button_Click(object sender, RoutedEventArgs e)
{
Storyboard sb = new Storyboard();
DoubleAnimation da = new DoubleAnimation();
da.BeginTime = TimeSpan.FromMilliseconds(0);
da.Duration = new Duration(TimeSpan.FromMilliseconds(1000));
da.From=1;
da.To = 0;
sb.Children.Add(da);
Storyboard.SetTargetProperty(da, new PropertyPath("(UIElement.Opacity)"));
Storyboard.SetTarget(da, this.LayoutRoot.Children[0]);
sb.Completed += delegate(Object o, EventArgs ea)
{
Random rnd=new Random();
((Ellipse)this.LayoutRoot.Children[0]).Fill = new SolidColorBrush(Color.FromArgb(255, (byte)rnd.Next(255), (byte)rnd.Next(255), (byte)rnd.Next(255)));
sb = new Storyboard();
da = new DoubleAnimation();
da.BeginTime = TimeSpan.FromMilliseconds(0);
da.Duration = new Duration(TimeSpan.FromMilliseconds(1000));
da.From=0;
da.To=1;
sb.Children.Add(da);
Storyboard.SetTargetProperty(da, new PropertyPath("(UIElement.Opacity)"));
Storyboard.SetTarget(da, this.LayoutRoot.Children[0]);
sb.Begin();
//done!
};
sb.Begin();
}
Good eh?