Today I found another issue concerning Silverlight 2.0 animations: If you reference the same object in one storyboard multiple times you receive a "Catastrophic Failure" error:

You can use the following code to reproduce the error. This code snippet should fade in an image and fade it out again immediately after the first animation has finished:
<UserControl x:Class="SilverlightApplication2.Page"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Canvas x:Name="LayoutRoot" Background="White">
<Image x:Name="Image2" Source="/6_Schuss_2_klein.png" Opacity="0" Width="54" Canvas.ZIndex="1" />
<Image x:Name="Image1" Source="/6_Schuss_1_klein.png" Opacity="0" Canvas.ZIndex="0" />
</Canvas>
</UserControl>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
namespace SilverlightApplication2
{
public partial class Page : UserControl
{
Storyboard storyboard;
public Page()
{
InitializeComponent();
Loaded+=new RoutedEventHandler(Page_Loaded);
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
try
{
storyboard = new Storyboard();
var animation = new DoubleAnimation();
Storyboard.SetTargetName(animation, "Image1");
Storyboard.SetTargetProperty(animation, "Opacity");
animation.To = 1;
animation.Duration = TimeSpan.FromSeconds(2);
storyboard.Children.Add(animation);
Resources.Add(storyboard);
Note that this second animation starts after the first animation (because of BeginTime). It references the same image as the first animation!
animation = new DoubleAnimation();
Storyboard.SetTargetName(animation, "Image1");
Storyboard.SetTargetProperty(animation, "Opacity");
animation.To = 0;
animation.Duration = TimeSpan.FromSeconds(2);
animation.BeginTime = TimeSpan.FromSeconds(2);
storyboard.Children.Add(animation);
storyboard.Begin();
}
catch (Exception ex)
{
}
}
}
}
storyboard.Begin throws the exception shown above.
However, if you try the same code with two different images everything runs fine:
using [...];
namespace SilverlightApplication2
{
public partial class Page : UserControl
{
[...]
void Page_Loaded(object sender, RoutedEventArgs e)
{
try
{
storyboard = new Storyboard();
var animation = new DoubleAnimation();
Storyboard.SetTargetName(animation, "Image1");
Storyboard.SetTargetProperty(animation, "Opacity");
animation.To = 1;
animation.Duration = TimeSpan.FromSeconds(2);
storyboard.Children.Add(animation);
Resources.Add(storyboard);
Note that this time the second animation refrences a different image object than the first one!
animation = new DoubleAnimation();
Storyboard.SetTargetName(animation, "Image2");
Storyboard.SetTargetProperty(animation, "Opacity");
animation.To = 1;
animation.Duration = TimeSpan.FromSeconds(2);
animation.BeginTime = TimeSpan.FromSeconds(2);
storyboard.Children.Add(animation);
storyboard.Begin();
}
catch (Exception ex)
{
}
}
}
}
If you try the first sample which throws the exception in Silverlight in WPF you will see that it works fine there. Therefore I think the behavior described above is a bug in Silverlight 2.0 Beta 1.
Just for the sake of completeness here is the WPF code that demonstrates two animations on a single object. In contrast to Silverlight it works:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
namespace WpfApplication2
{
public partial class Window1 : Window
{
Storyboard storyboard;
public Window1()
{
InitializeComponent();
Loaded += new RoutedEventHandler(Page_Loaded);
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
try
{
storyboard = new Storyboard();
var animation = new DoubleAnimation();
Storyboard.SetTargetName(animation, "Image1");
Storyboard.SetTargetProperty(animation, new PropertyPath(Image.OpacityProperty));
animation.To = 1;
animation.Duration = TimeSpan.FromSeconds(1);
storyboard.Children.Add(animation);
Resources.Add("sb", storyboard);
animation = new DoubleAnimation();
Storyboard.SetTargetName(animation, "Image1");
Storyboard.SetTargetProperty(animation, new PropertyPath(Image.OpacityProperty));
animation.To = 0;
animation.Duration = TimeSpan.FromSeconds(1);
animation.BeginTime = TimeSpan.FromSeconds(1);
storyboard.Children.Add(animation);
storyboard.Begin(this);
}
catch (Exception ex)
{
}
}
}
}