7

基本上,我想制作一堆形状并让它们动画化。所以我想出了以下自定义类:

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.Add)添加它,它就不起作用。让我看看我是否能找出原因。

4

4 回答 4

6

好的,

我已经找到了解决框架中显然是一个错误的解决方法(尽管我确信一些 MS 员工会发布回复并说这是一个功能/它是设计的)。需要做几件事:

  1. 添加默认/无参数构造函数
  2. 将 FunkyShape 的基类更改为 UserControl。
  3. 打开要在其中添加形状的 Page 类的 XAML 视图
  4. 在 Canvas XAML 中添加一个 FunkyShape 实例作为子项(例如 <tm:FunkyShape />)。没有这个就行不通。
  5. 在代码隐藏中创建一个 FunkyShape 实例,将其添加到画布,启动动画并享受它的工作原理
  6. 切换到错误更少的技术。
于 2012-10-16T22:18:19.730 回答
3

在 Windows 8 中,如果不将 enabledependentanimation 属性设置为 true,则无法为自定义属性设置动画。这是因为默认情况下禁用了非确定性动画。

参考:http: //msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.animation.pointanimation.enabledependentanimation.aspx

于 2012-10-16T17:15:22.300 回答
1

是的,您必须将此属性定义为依赖属性,而不仅仅是常规的 CLR 属性。这涉及相当多的简单样板代码。有关完整示例,请参见博客文章:

http://timheuer.com/blog/archive/2012/03/07/creating-custom-controls-for-metro-style-apps.aspx

于 2012-10-15T07:03:11.713 回答
1

好的,我也有这个问题,但是我不想在我的类中包含一个公共的无参数构造函数,所以我找到了另一种方法。

基本上,问题在于 WinRT 是一个原生平台,它不能对 .NET 代码进行反射。这就是 WinRT 应用程序的生成过程生成有关 XAML 中使用的类型的元数据的原因(您可以在 中找到相关代码obj/(Debug|Release)/XamlTypeInfo.g.cs)。

如果在 XAML 中从未使用过某个类型,则不会生成有关此类型的元数据,这意味着(除其他外)您无法为该类型的属性设置动画。

如果您正在编写一个类库,您可以只包含一个 XAML 资源字典并声明该类型的一个虚拟实例;它将导致生成元数据。但是,它要求该类型有一个公共的无参数构造函数,这可能是不可取的。

所以还有另一种解决方案:自己提供元数据。有几个接口要实现,并且它们有很多成员,因此手动执行可能会非常乏味。幸运的是,您不必这样做!以下是您可以执行的操作:

  • 向类添加公共无参数构造函数(临时)
  • 创建一个 XAMLResourceDictionary并在其中声明一个类的实例(如上所述)
  • 将文件复制XamlTypeInfo.g.cs到您的项目中(我将其重命名为XamlTypeInfo.cs
  • 将对构造函数的调用替换为throw new NotImplementedException()
  • 删除ResourceDictionary文件
  • 删除公共无参数构造函数

大功告成,动画现在可以正常工作了。

这个过程仍然很繁琐,所以有一个工具来为我们完成工作会很好......


编辑:简单的解决方案:将[Bindable]属性应用于类。它使元数据生成器将类型考虑在内,即使它未在 XAML 中使用。(忽略文档说它适用于 C++ 类型的事实;它也适用于 C# 类)

于 2014-10-06T21:54:29.267 回答