Цель анимации не указана - раскадровки Silverlight

Здесь происходит настоящая царапина, потому что я не могу понять, почему я получаю цель анимации, не указавшую ошибку. Я создаю статический класс для раздачи раскадровок множества маленьких "горящих" огней. Затем я создаю столько пожаров, сколько захочет пользователь, и назначаю ему новую раскадровку, все в Csharp. Затем я начинаю раскадровку, но, как я уже сказал, я получаю эту ошибку и не могу понять, почему. Вот класс создания раскадровки, и когда я пытаюсь вызвать его.

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 EasingColorKeyFrame();
        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;
    }
}

И вот где я назначаю его каждому изображению огня:

Storyboard fireStoryboard = FireStoryboard.fireStoryboard(fire);
        fireStoryboard.Begin();

Любая помощь будет принята с благодарностью. Я пропускаю установку цели где-нибудь? Я действительно не могу видеть, где:(.

1 ответ

Решение

Следующее прекрасно работает для меня, когда elementName x:Name можно найти в элементе, у которого есть раскадровка в его ресурсах. При реализации MVVM вы также можете установить имя на лету, потому что тогда вам больше не понадобится x: Name в любом случае. Смотрите следующее;

    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();
            }
        }
    }

Когда раскадровка завершается, я очищаю ресурсы, что значительно повышает производительность при использовании все большего количества раскадровок;)

    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);
            }
        }
    }

Вот статический метод, который создает для меня многоразовую раскадровку.

    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;
    }

И DoubleAnimationUsingKeyFrames, которые также могут быть другими типами анимации, как вам нравится.

    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;
    }

Дайте мне знать, если это было полезно, спасибо заранее.

Другие вопросы по тегам