代码之家  ›  专栏  ›  技术社区  ›  Robert Rossney

当我使用故事板时,为什么这些动画不起作用?

  •  9
  • Robert Rossney  · 技术社区  · 15 年前

    我已经创建了 StackPanel 我可以在屏幕上使用动画 TranslateTransform . 看起来是这样的:

    public class MovingStackPanel : StackPanel
    {
        public void BeginMove(Point translatePosition)
        {
            RenderTransform = new TranslateTransform();
            Duration d = new Duration(new TimeSpan(0, 0, 0, 0, 400));
            DoubleAnimation x = new DoubleAnimation(translatePosition.X, d);
            DoubleAnimation y = new DoubleAnimation(translatePosition.Y, d);
            /*
            Storyboard.SetTarget(x, RenderTransform);
            Storyboard.SetTargetProperty(x, new PropertyPath("X"));
    
            Storyboard.SetTarget(y, RenderTransform);
            Storyboard.SetTargetProperty(y, new PropertyPath("Y"));
    
            Storyboard sb = new Storyboard();
            sb.Children.Add(x);
            sb.Children.Add(y);
            sb.Completed += sb_Completed;
            sb.Begin();
            */
            RenderTransform.BeginAnimation(TranslateTransform.XProperty, x);
            RenderTransform.BeginAnimation(TranslateTransform.YProperty, y);
        }
    
        void sb_Completed(object sender, EventArgs e)
        {
            Console.WriteLine("Completed.");
        }
    } 
    

    这里是我的问题:如果我像上面的代码那样直接设置x和y属性的动画,它就会工作。但如果我使用上面的注释掉的代码,这实际上是 Storyboard 在可以想象的代码中,什么都没有发生。动画运行-至少,完成的事件会被引发-但屏幕上没有任何变化。

    显然我做错了什么,但我看不出是什么。我所看到的用代码创建故事板的每个例子都是这样的。很明显,关于动画和故事板的一些东西我还不知道:是什么?

    2 回复  |  直到 13 年前
        1
  •  10
  •   Robert Rossney    15 年前

    事实证明,在这种情况下,不能使用属性路径语法,因为要设置动画的属性不是 FrameworkElement . 至少,当我做出安瓦卡建议的改变时,我是这样理解这个令人困惑的例外的:

    Cannot automatically create animation clone for frozen property values on     
    'System.Windows.Media.TranslateTransform' objects. Only FrameworkElement and 
    FrameworkContentElement (or derived) types are supported.
    

    要使它们成为动画,我必须使用 NameScope 和使用 SetTargetName 命名 TransformElement . 那么,只要我通过 框架元素 我将名称范围设置为 Begin 方法,故事板可以找到对象和属性,并对它们进行动画处理,一切都可以工作。最终结果如下:

    public void BeginMove(Point translatePosition)
    {
        NameScope.SetNameScope(this, new NameScope());
    
        RenderTransform = new TranslateTransform();
        RegisterName("TranslateTransform", RenderTransform);
    
        Duration d = new Duration(new TimeSpan(0, 0, 0, 0, 400));
        DoubleAnimation x = new DoubleAnimation(translatePosition.X, d);
        DoubleAnimation y = new DoubleAnimation(translatePosition.Y, d);
    
        Storyboard.SetTargetName(x, "TranslateTransform");
        Storyboard.SetTargetProperty(x, new PropertyPath(TranslateTransform.XProperty));
    
        Storyboard.SetTargetName(y, "TranslateTransform");
        Storyboard.SetTargetProperty(y, new PropertyPath(TranslateTransform.YProperty));
    
        Storyboard sb = new Storyboard();
        sb.Children.Add(x);
        sb.Children.Add(y);
        sb.Completed += sb_Completed;
    
        // you must pass this to the Begin method, otherwise the timeline won't be
        // able to find the named objects it's animating because it doesn't know
        // what name scope to look in
    
        sb.Begin(this);
    
    }
    
        2
  •  8
  •   Michael Goldshteyn    13 年前

    它是 property path 语法。以下方法有效:

    public void BeginMove(Point translatePosition)
    {
      RenderTransform = new TranslateTransform();
      Duration d = new Duration(new TimeSpan(0, 0, 0, 0, 400));
      DoubleAnimation x = new DoubleAnimation(translatePosition.X, d);
      DoubleAnimation y = new DoubleAnimation(translatePosition.Y, d);
    
      Storyboard.SetTarget(x, this);
      Storyboard.SetTargetProperty(x, 
                  new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));
    
      Storyboard.SetTarget(y, this);
      Storyboard.SetTargetProperty(y, 
                  new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));
    
      Storyboard sb = new Storyboard();
      sb.Children.Add(x);
      sb.Children.Add(y);
      sb.Completed += sb_Completed;
      sb.Begin();
    
      //RenderTransform.BeginAnimation(TranslateTransform.XProperty, x);
      //RenderTransform.BeginAnimation(TranslateTransform.YProperty, y);
    }