基本上,我想制作一堆Shapes并让它们变得生动。所以我提出了以下自定义类:
public class FunkyShape : DependencyObject
{
public double Animator
{
get { return (double)GetValue(AnimatorProperty); }
set { SetValue(AnimatorProperty, value); }
}
public static readonly DependencyProperty AnimatorProperty =
DependencyProperty.Register("Animator", typeof(double), typeof(FunkyShape),
new PropertyMetadata(0, new PropertyChangedCallback(Animator_Changed)));
private static void Animator_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
double delta = (double)e.NewValue - (double)e.OldValue;
((FunkyShape)d).ProcessDelta((double)e.NewValue, delta);
}
private void ProcessDelta(double val, double delta)
{
Holder.Width = val;
Holder.Height = val;
// Keep shape centered
HolderPosition.X = delta / 2;
HolderPosition.Y = delta / 2;
}
private Shape Holder;
public TranslateTransform HolderPosition
{
get { return (TranslateTransform)Holder.RenderTransform; }
}
public FunkyShape(Canvas playground, Shape shapeToInit)
{
Holder = shapeToInit;
Holder.Width = 10;
Holder.Height = 10;
Holder.Fill = new SolidColorBrush(Colors.Blue);
Holder.HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Center;
Holder.RenderTransform = new TranslateTransform()
{
X = 500,
Y = 500
};
Holder.RenderTransformOrigin = new Point(0.5, 0.5);
// init done
playground.Children.Add(Holder);
Animate();
}
public void Animate()
{
DoubleAnimation g1 = GrowAnimation();
Storyboard sb = new Storyboard();
Storyboard.SetTarget(g1, this);
// CAN'T FIND ANIMATOR PROPERTY
Storyboard.SetTargetProperty(g1, "Animator");
sb.Children.Add(g1);
sb.Begin(); // THROWS EXCEPTION
}
private static DoubleAnimation GrowAnimation()
{
DoubleAnimation growAnimation = new DoubleAnimation();
growAnimation.Duration = TimeSpan.FromMilliseconds(3000);
growAnimation.From = 0;
growAnimation.To = 100;
growAnimation.AutoReverse = true;
growAnimation.EnableDependentAnimation = true;
growAnimation.RepeatBehavior = new RepeatBehavior(5);
return growAnimation;
}
}
然而,当我尝试创建类的实例并将其添加到画布时,我得到了Exception - Storyboard.Being()抛出它并告诉我它无法找到Animator属性。
那么 - 我做错了什么?
编辑: 3次更改代码后仍然无效;我得到“无法解析指定对象上的TargetProperty Animator”错误。所以,如果有人知道答案 - 请通过修改代码来帮助。谢谢!
编辑:好吧,经过24小时撞击墙壁后有一些进展 - 如果我通过XAML添加形状它会动画,但如果我通过代码添加它(Canvas.Children。添加),它不起作用。让我看看能否找出原因。
答案 0 :(得分:6)
行,
我已经找到了解决框架中明显是一个错误的解决方法(虽然我确信某些MS员工会发布回复并说它是一个功能/它是设计的)。有几件事需要做:
答案 1 :(得分:3)
在Windows 8中,如果不将enabledependentanimation属性设置为true,则无法为自定义属性设置动画。这是因为默认情况下禁用非确定性动画。
答案 2 :(得分:1)
是的,您必须将此属性定义为依赖项属性,而不仅仅是常规CLR属性。这涉及相当多的简单锅炉板代码。请参阅博客文章以获取完整示例:
http://timheuer.com/blog/archive/2012/03/07/creating-custom-controls-for-metro-style-apps.aspx
答案 3 :(得分:1)
好吧,我也有这个问题,但我不想在我的课程中包含一个公共无参数构造函数,所以我找到了另一种方法。
基本上,问题是WinRT是一个原生平台,它无法对.NET代码进行反思。这就是为什么WinRT应用程序的构建过程会生成有关XAML中使用的类型的元数据的原因(您可以在obj/(Debug|Release)/XamlTypeInfo.g.cs
中找到相关代码)。
如果在XAML中从未使用过类型,则不会生成有关此类型的元数据,这意味着(除其他外)您无法为该类型的属性设置动画。
如果您正在编写类库,则可以只包含一个XAML资源字典并声明该类型的虚拟实例;它将导致生成元数据。但是,它要求类型具有公共无参数构造函数,这可能是不可取的。
所以还有另一种解决方案:自己提供元数据。有几个接口要实现,它们有很多成员,因此手动操作可能非常繁琐。幸运的是,你不必!以下是您可以做的事情:
ResourceDictionary
并在其中声明该类的实例(如上所述)XamlTypeInfo.g.cs
文件复制到您的项目中(我将其重命名为XamlTypeInfo.cs
)throw new NotImplementedException()
ResourceDictionary
文件你完成了,动画现在正常运作。
这个过程仍然很乏味,所以有一个工具为我们做这项工作会很好......
编辑:很多更简单的解决方案:将[Bindable]
属性应用于该类。它使元数据生成器将类型考虑在内,即使它未在XAML中使用。 (忽略文档说它适用于C ++类型的事实;它在C#类上也可以正常工作)