我创建了一个简单的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
的最简单的创建,没有任何反应。动画运行 - 至少,已完成事件被提升 - 但屏幕上没有任何变化。
显然我做错了什么,但我看不出它是什么。在我看过的代码中创建故事板的每个例子看起来都是这样的。很明显我还不知道动画和故事板的内容:它是什么?
答案 0 :(得分: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);
}
答案 1 :(得分:8)
这是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);
}