[英]Windows 8 - Animating custom property in code-behind
Basically, I want to make bunch of Shapes and make them animated. 基本上,我想制作一堆Shapes并让它们变得生动。 So I came up with following custom class: 所以我提出了以下自定义类:
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;
}
}
However, when I try making an instance of the class and adding it to the canvas, I get Exception - Storyboard.Being() throws it and tells me that it can't find Animator property. 但是,当我尝试创建类的实例并将其添加到画布时,我得到Exception - Storyboard.Being()抛出它并告诉我它无法找到Animator属性。
So - what am I doing wrong? 那么 - 我做错了什么?
EDIT: After 3 code changes - it is still not working; 编辑: 3代码更改后 - 它仍然无法正常工作; I get "Cannot resolve TargetProperty Animator on specified object" error. 我得到“无法解析指定对象上的TargetProperty Animator”错误。 So if somebody knows the answer - please help out by modifying the code. 所以,如果有人知道答案 - 请通过修改代码来帮助。 Thanks! 谢谢!
EDIT: OK, after 24 hours of banging head against the wall there is some progress - if I add shape through XAML it animates, but if I add it through code behind (Canvas.Children.Add), it doesn't work. 编辑:好的,经过24小时撞击墙壁后有一些进展 - 如果我通过XAML添加形状它动画,但如果我通过代码后面添加它(Canvas.Children.Add),它不起作用。 Let me see if I can figure out why. 让我看看能否找出原因。
OK, 好,
I've found the workaround for what is obviously a bug within the framework (although I'm sure some MS employee will post response and say it's a feature/it-is-by-design). 我已经找到了解决方案,因为这显然是框架内的一个错误(虽然我确信一些MS员工会发布回复并说它是一个功能/它是按设计)。 Several things need to be done: 有几件事需要做:
In Windows 8 you cannot animate custom properties without also setting the enabledependentanimation property to true. 在Windows 8中,如果不将enabledependentanimation属性设置为true,则无法为自定义属性设置动画。 This is because non-deterministic animations are disabled by default. 这是因为默认情况下禁用非确定性动画。
Reference: http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.animation.pointanimation.enabledependentanimation.aspx 参考: http : //msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.animation.pointanimation.enabledependentanimation.aspx
Yes, you must define this property as a dependency property, not just a regular CLR property. 是的,您必须将此属性定义为依赖项属性,而不仅仅是常规CLR属性。 This involves quite a bit of simple boiler plate code. 这涉及相当多的简单锅炉板代码。 See thus blog post for a complete example: 请参阅博客文章以获取完整示例:
http://timheuer.com/blog/archive/2012/03/07/creating-custom-controls-for-metro-style-apps.aspx http://timheuer.com/blog/archive/2012/03/07/creating-custom-controls-for-metro-style-apps.aspx
OK, I had this problem too, but I didn't want to include a public parameterless constructor in my class, so I found another way. 好吧,我也有这个问题,但我不想在我的课程中包含一个公共无参数构造函数,所以我找到了另一种方法。
Basically, the issue is that WinRT is a native platform, and it can't do reflection on .NET code. 基本上,问题是WinRT是一个原生平台,它无法对.NET代码进行反思。 That's why the build process for WinRT apps generates metadata about the types used in XAML (you can find the relevant code in obj/(Debug|Release)/XamlTypeInfo.g.cs
). 这就是为什么WinRT应用程序的构建过程会生成有关XAML中使用的类型的元数据(您可以在obj/(Debug|Release)/XamlTypeInfo.g.cs
找到相关代码)。
If a type is never used in XAML, no metadata about this type is generated, which means (among other things) that you can't animate the properties of the type. 如果从未在XAML中使用类型,则不会生成有关此类型的元数据,这意味着(除其他外)您无法为该类型的属性设置动画。
If you're writing a class library, you can just include a XAML resource dictionary and declare a dummy instance of the type; 如果您正在编写类库,则可以只包含一个XAML资源字典并声明该类型的虚拟实例; it will cause metadata to be generated. 它将导致生成元数据。 However, it requires that the type has a public parameterless constructor, which might not be desirable. 但是,它要求类型具有公共无参数构造函数,这可能是不可取的。
So there is another solution: provide the metadata yourself. 所以还有另一种解决方案:自己提供元数据。 There are a several interfaces to implement, and they have many members, so it can be quite tedious to do manually. 有几个接口要实现,它们有很多成员,因此手动操作可能非常繁琐。 Fortunately, you don't have to! 幸运的是,你没必要! Here's what you can do: 这是你可以做的:
ResourceDictionary
and declare an instance of the class in it (as described above) 创建一个XAML ResourceDictionary
并在其中声明该类的实例(如上所述) XamlTypeInfo.g.cs
file into your project (I renamed it to XamlTypeInfo.cs
) 将XamlTypeInfo.g.cs
文件复制到项目中(我将其重命名为XamlTypeInfo.cs
) throw new NotImplementedException()
用throw new NotImplementedException()
替换对构造函数的调用 ResourceDictionary
file 删除ResourceDictionary
文件 And you're done, the animation now works properly. 而且你已经完成了,动画现在可以正常运行了。
The process is still quite tedious, so it would be nice to have a tool to do the work for us... 这个过程仍然很乏味,所以有一个工具为我们做这项工作会很好...
EDIT: much easier solution: apply the [Bindable]
attribute to the class. 编辑: 更简单的解决方案:将[Bindable]
属性应用于类。 It makes the metadata generator take the type into account even if it's not used in XAML. 它使元数据生成器将类型考虑在内,即使它未在XAML中使用。 (ignore the fact that the doc says it's for C++ types; it works just fine on C# classes as well) (忽略文档说它适用于C ++类型的事实;它在C#类上也可以正常工作)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.