简体   繁体   English

Windows 8 - 在代码隐藏中设置自定义属性的动画

[英]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: 有几件事需要做:

  1. Add default/parameter-less constructor 添加default / parameter-less构造函数
  2. Change base class of FunkyShape to UserControl. 将FunkyShape的基类更改为UserControl。
  3. Open up XAML view of the Page class where you want to add shapes 打开要添加形状的Page类的XAML视图
  4. Add one instance of FunkyShape as a child within the Canvas XAML (<tm:FunkyShape /> for example). 在Canvas XAML中添加一个FunkyShape实例作为子项(例如<tm:FunkyShape />)。 IT WON'T WORK WITHOUT THIS. 它不会没有这个。
  5. Make an instance of FunkyShape in code-behind, add it to canvas, start animation and enjoy seeing it works 在代码隐藏中创建一个FunkyShape实例,将其添加到画布,启动动画并欣赏它的工作原理
  6. Switch to less buggy technology. 切换到更少的马车技术。

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: 这是你可以做的:

  • add a public parameterless constructor to the class (temporarily) 向该类添加一个公共无参数构造函数(暂时)
  • create a XAML ResourceDictionary and declare an instance of the class in it (as described above) 创建一个XAML ResourceDictionary并在其中声明该类的实例(如上所述)
  • copy the XamlTypeInfo.g.cs file into your project (I renamed it to XamlTypeInfo.cs ) XamlTypeInfo.g.cs文件复制到项目中(我将其重命名为XamlTypeInfo.cs
  • replace the call to the constructor with throw new NotImplementedException() throw new NotImplementedException()替换对构造函数的调用
  • delete the ResourceDictionary file 删除ResourceDictionary文件
  • remove the public parameterless constructor 删除public parameterless构造函数

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM