Animation target not specified issue - Silverlight storyboards
Having some real head scratching going on here as I can't seem to think why I am getting the Animation target not specified error. I create a static class for dishing out storyboards of lots of little fires "burning". I then create as many of those fires as the user wants and assign a new storyboard to it, all in Csharp. I then begin then storyboard, but as I say, I keep getting this error and I can't seem why. Here is the storyboard creating class, and when I try to call it.
public static class FireStoryboard
{
public static Storyboard fireStoryboard(UIElement target)
{
Storyboard s = new Storyboard();
s.RepeatBehavior = RepeatBehavior.Forever;
DoubleAnimationUsingKeyFrames scaleY = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(scaleY, target);
scaleY.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.ScaleY)"));
EasingDoubleKeyFrame e1 = new EasingDoubleKeyFrame();
e1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
e1.Value = 1.8;
e1.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
EasingDoubleKeyFrame e2 = new EasingDoubleKeyFrame();
e2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2));
e1.Value = 1;
e2.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
scaleY.KeyFrames.Add(e1);
scaleY.KeyFrames.Add(e2);
DoubleAnimationUsingKeyFrames translateY = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(translateY, target);
translateY.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)"));
EasingDoubleKeyFrame e3 = new EasingDoubleKeyFrame();
e3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
e3.Value = -4;
e3.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
EasingDoubleKeyFrame e4 = new EasingDoubleKeyFrame();
e4.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2));
e4.Value = 0;
e4.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
translateY.KeyFrames.Add(e3);
translateY.KeyFrames.Add(e4);
DoubleAnimationUsingKeyFrames opacity = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(opacity, target);
opacity.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("UIElement.Opacity"));
EasingDoubleKeyFrame e5 = new EasingDoubleKeyFrame();
e5.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
e5.Value = 0.7;
EasingDoubleKeyFrame e6 = new EasingDoubleKeyFrame();
e6.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
e6.Value = 1;
EasingDoubleKeyFrame e7 = new EasingDoubleKeyFrame();
e7.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2));
e7.Value = 0.7;
opacity.KeyFrames.Add(e5);
opacity.KeyFrames.Add(e6);
opacity.KeyFrames.Add(e7);
DoubleAnimationUsingKeyFrames shadowDirection = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(shadowDirection, target);
shadowDirection.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.Effect).(DropShadowEffect.Direction)"));
EasingDoubleKeyFrame eShad1 = new EasingDoubleKeyFrame();
eShad1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
eShad1.Value = 449;
EasingDoubleKeyFrame eShad2 = new EasingDoubleKeyFrame();
eShad2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
eShad2.Value = 449;
shadowDirection.KeyFrames.Add(eShad1);
shadowDirection.KeyFrames.Add(eShad2);
DoubleAnimationUsingKeyFrames shadowDepth = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(shadowDepth, target);
shadowDirection.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.Effect).(DropShadowEffect.ShadowDepth)"));
EasingDoubleKeyFrame eShad3 = new EasingDoubleKeyFrame();
eShad3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
eShad3.Value = 0;
EasingDoubleKeyFrame eShad4 = new EasingDoubleKeyFrame();
eShad4.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
eShad4.Value = 5;
EasingDoubleKeyFrame eShad5 = new EasingDoubleKeyFrame();
eShad5.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2));
eShad5.Value = 20;
shadowDirection.KeyFrames.Add(eShad3);
shadowDirection.KeyFrames.Add(eShad4);
shadowDirection.KeyFrames.Add(eShad5);
DoubleAnimationUsingKeyFrames shadowOpacity = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(shadowOpacity, target);
shadowDirection.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.Effect).(DropShadowEffect.Opacity)"));
EasingDoubleKeyFrame eShad6 = new EasingDoubleKeyFrame();
eShad6.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
eShad6.Value = 1;
EasingDoubleKeyFrame eShad7 = new EasingDoubleKeyFrame();
eShad7.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2));
eShad7.Value = 0;
shadowDirection.KeyFrames.Add(eShad6);
shadowDirection.KeyFrames.Add(eShad7);
DoubleAnimationUsingKeyFrames skewX = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(skewX, target);
skewX.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.SkewX)"));
EasingDoubleKeyFrame eSkew1 = new EasingDoubleKeyFrame();
eSkew1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
eSkew1.Value = 0;
eSkew1.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
EasingDoubleKeyFrame eSkew2 = new EasingDoubleKeyFrame();
eSkew2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5));
eSkew2.Value = -5;
eSkew2.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
EasingDoubleKeyFrame eSkew3 = new EasingDoubleKeyFrame();
eSkew3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
eSkew3.Value = 5;
eSkew3.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
EasingDoubleKeyFrame eSkew4 = new EasingDoubleKeyFrame();
eSkew4.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1.5));
eSkew4.Value = -5;
eSkew4.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
EasingDoubleKeyFrame eSkew5 = new EasingDoubleKeyFrame();
eSkew5.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2));
eSkew5.Value = 0;
eSkew5.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
skewX.KeyFrames.Add(eSkew1);
skewX.KeyFrames.Add(eSkew2);
skewX.KeyFrames.Add(eSkew3);
skewX.KeyFrames.Add(eSkew4);
skewX.KeyFrames.Add(eSkew5);
ColorAnimationUsingKeyFrames shadowColor = new ColorAnimationUsingKeyFrames();
Storyboard.SetTarget(shadowColor, target);
shadowColor.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.Effect).(DropShadowEffect.Color)"));
EasingColorKeyFrame eColor1 = new EasingColorKeyFrame();
eColor1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
eColor1.Value = Colors.Red;
EasingColorKeyFrame eColor2 = new EasingColorKeyFrame();
eColor2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5));
eColor2.Value = Color.FromArgb(255, 254, 31, 0);
EasingColorKeyFrame eColor3 = new EasingCol开发者_StackOverflow中文版orKeyFrame();
eColor3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.7));
eColor3.Value = Color.FromArgb(255, 254, 255, 0);
EasingColorKeyFrame eColor4 = new EasingColorKeyFrame();
eColor4.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.8));
eColor4.Value = Colors.Black;
shadowColor.KeyFrames.Add(eColor1);
shadowColor.KeyFrames.Add(eColor2);
shadowColor.KeyFrames.Add(eColor3);
shadowColor.KeyFrames.Add(eColor4);
s.Children.Add(scaleY);
s.Children.Add(translateY);
s.Children.Add(opacity);
s.Children.Add(shadowDirection);
s.Children.Add(shadowDepth);
s.Children.Add(shadowOpacity);
s.Children.Add(skewX);
s.Children.Add(shadowColor);
Storyboard.SetTarget(s, target);
return s;
}
}
And here is where I assign it to each fire image:
Storyboard fireStoryboard = FireStoryboard.fireStoryboard(fire);
fireStoryboard.Begin();
Any help would be greatly appreciated. Am I missing setting a target somewhere? I really cannot see where :(.
The following works fine for me when the elementName x:Name can be found in the element which has the Storyboard in it's resources. When implementing MVVM you can also set the name on the fly because then you don't need the x:Name most of the time any way. See the following;
private void GoShowUpElement(FrameworkElement element, double opacity)
{
if (element != null)
{
string guidString = Guid.NewGuid().ToString();
element.SetValue(NameProperty, guidString);// When you don't use x:Name in Xaml (with MVVM normally not nessasary)
if (!this.LayoutRoot.Resources.Contains(guidString))
{
this.LayoutRoot.Resources.Add(guidString, ShowUpElement(opacity, 1000, guidString)); // when you do use x:Name replace guidString with the x:Name you used.
Storyboard simultaniousStoryboard = this.LayoutRoot.Resources[guidString] as Storyboard;
simultaniousStoryboard.Completed += new EventHandler(simultaniousStoryboard_Completed);
simultaniousStoryboard.Begin();
}
}
}
When the storyboard completes, I clean up the resources, which significantly increases performance when using more and more storyboards ;)
private void simultaniousStoryboard_Completed(object sender, EventArgs e)
{
Storyboard storyboard = sender as Storyboard;
foreach (DictionaryEntry dictionaryEntry in this.LayoutRoot.Resources)
{
Storyboard resourceStoryboard = dictionaryEntry.Value as Storyboard;
if (resourceStoryboard != null)
{
if (resourceStoryboard.GetValue(NameProperty) == storyboard.GetValue(NameProperty))
this.LayoutRoot.Resources.Remove(dictionaryEntry.Key);
}
}
}
Here is the static Method that creates a reusable storyboard for me.
public static Storyboard ShowUpElement(double opacity, int milliseconds, string elementName)
{
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(StoryboardBasic.KeyFramedAnimation(opacity, 0.9, 0, milliseconds, elementName, "Opacity"));
//storyboard.Children.Add(StoryboardBasic.KeyFramedAnimation.... Add more if you want
return storyboard;
}
And the DoubleAnimationUsingKeyFrames which could also be other types of animations as you like.
public static DoubleAnimationUsingKeyFrames KeyFramedAnimation(double fromValue, double toValue, int startMilliSeconds, int endMilliseconds, string targetElementName, PropertyPath propertyPath)
{
List<SplineDoubleKeyFrame> splineDoubleKeyFrames = new List<SplineDoubleKeyFrame>()
{
new SplineDoubleKeyFrame() { KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(startMilliSeconds)), Value = fromValue, KeySpline = new KeySpline() { ControlPoint1 = new Point(0,0), ControlPoint2= new Point(1,0)} },
new SplineDoubleKeyFrame() { KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(endMilliseconds)), Value = toValue, KeySpline = new KeySpline() { ControlPoint1 = new Point(0,0), ControlPoint2= new Point(0,1)} },
};
DoubleAnimationUsingKeyFrames animation = new DoubleAnimationUsingKeyFrames();
foreach (SplineDoubleKeyFrame linearDoubleKeyFrame in splineDoubleKeyFrames)
animation.KeyFrames.Add(linearDoubleKeyFrame);
Storyboard.SetTargetName(animation, targetElementName);
Storyboard.SetTargetProperty(animation, propertyPath);
return animation;
}
Let me know if this was helpfull, Thanks in advance.
精彩评论