2010-02-26 55 views
8

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

显然我做错了什么,但我看不到它是什么。在我看到的代码中创建故事板的每个示例都与此类似。显然还有一些我还不知道的动画和故事板:它是什么?

+1

仅供参考 - 我将其作为Microsoft Connect上的一个错误发布。 https://connect.microsoft.com/VisualStudio/feedback/details/723701/storyboard-settarget-only-works-on-uielements-but-throws-no-exception – 2012-02-06 19:16:13

回答

10

事实证明,你不能在这种情况下使用属性路径语法,因为属性被动画不是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. 

要动态的,现在看来,我必须使用一个NameScope和使用SetTargetName命名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); 

} 
7

这是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); 
} 
相关问题