11

我创建了一个简单的子类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可以想象的最简单的 in 代码创建,则什么也不会发生。动画运行 - 至少, Completed 事件被引发 - 但屏幕上没有任何变化。

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

4

2 回答 2

13

事实证明,在这种情况下,您不能使用属性路径语法,因为正在动画的属性不是 a 的属性FrameworkElement。至少,当我做出 Anvaka 建议的更改时,我是这样解释我得到的非常令人困惑的异常:

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

为了使这些动画化,似乎我必须使用 aNameScope和 useSetTargetName来命名TransformElement. 然后,只要我将FrameworkElement我设置的名称范围传递给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);

}
于 2010-02-26T08:35:08.500 回答
8

这是属性路径语法。以下方法有效:

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);
}
于 2010-02-26T07:05:28.790 回答