如何用windows8 metro&windows phone自定义依赖属性绑定动画

在做动画的时候如果使用自定义的依赖属性来绑定动画,将会使我们软件的整体架构得到很大的提升,实现动画与页面逻辑的分离。

在wp7上我们能很轻松的实现这个效果。

假如我们需要界面上的一个按钮做运动。

xaml:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
      <Button Name="btnAnimal" Content="Button" VerticalAlignment="Top" Click="Button_Click_1"/>
 </Grid>

 后台:

        SlideTranslate slide = new SlideTranslate();
            slide.Add(btnAnimal);
            DoubleAnimation animation = new DoubleAnimation() { From = 0, To = 700, Duration = new Duration(TimeSpan.FromMilliseconds(1000)) };
            Storyboard.SetTarget(animation, slide);
            Storyboard.SetTargetProperty(animation, new PropertyPath("SlideTranslate.Y"));
            Storyboard sb = new Storyboard();
            sb.Children.Add(animation);
            sb.Begin();

 SlideTranslate:动画类。

public class SlideTranslate : DependencyObject
    {
        public static readonly DependencyProperty YProperty =
            DependencyProperty.Register("Y",
                typeof(double),
                typeof(SlideTranslate),
                new PropertyMetadata(-1.0, OnTransitionChanged));

        public static bool IsAnimal = false;

        public double Y
        {
            set { SetValue(YProperty, value); }
            get { return (double)GetValue(YProperty); }
        }

        static void OnTransitionChanged(DependencyObject obj,
                                        DependencyPropertyChangedEventArgs args)
        {
            (obj as SlideTranslate).OnTransitionChanged(args);
        }

        public FrameworkElement Element { get; set; }
        TranslateTransform t = new TranslateTransform();

        public void Add(FrameworkElement element)
        {
            element.RenderTransform = t;
            this.Element = element;
        }

        void OnTransitionChanged(DependencyPropertyChangedEventArgs args)
        {
            t.Y = Y;
        }
    }

 这样,我们就实现了动画与逻辑的分离。我们的后台代码不需要实现它做什么运动,只需要把那个依赖属性绑到动画上就可以了。

至于你做什么动画是由SlideTranslate它来决定的 。如果我们将OnTransitionChanged里面的方法改成t.X=Y;那么就是x横向的运动了。

这样我们就能借助一些接口抽象类等实现各种各样的效果,而且在架构上得到很大的提升。

但是到win8 的时候我们会发现这个方式根本行不通,因为会报错。

当然我们要把代码稍作更改

Storyboard.SetTargetProperty(animation, new PropertyPath("SlideTranslate.Y"));

改成Storyboard.SetTargetProperty(animation, "SlideTranslate.Y");

这样会发现报这个错误。

这里就关系到了一个 XamlTypeInfo 的内容,因为你的动画是通过代码添加的, 所以在反射这个属性的时候,他需要在XamlTypeInfo中寻找这个SlideTranslate的内容,以及他的属性列表。 但是它没有找到,因为VS没有为SlideTranslate在XamlTypeInfo中生成相应的信息。如果你在XAML只要添加过一次 <local:SlideTranslate.../>  VS就会生成此信息,你的动画就可以运行了。 当然这个解决办法你可以在XAML创建一个隐藏的SlideTranslate, 或者定义其为一个资源。

也就是说我们需要在xaml对SlideTranslate进行声明。

    <Page.Resources>
        <local:SlideTranslate x:Key="trans"></local:SlideTranslate>
    </Page.Resources>

 这样虽然不报错了,但是动画依然不执行 ,调试发现,OnTransitionChanged这个事件根本没被触发,也就是说属性Y的值没有发生变化。

不废话了,其实我们少了一个动画属性的设置。

anima.EnableDependentAnimation = true;

那么最后完整的代码如下

        SlideTranslate slide = new SlideTranslate();
            slide.Add(btnAnimal);
            DoubleAnimation animation = new DoubleAnimation() { From = 0, To = 700, Duration = new Duration(TimeSpan.FromMilliseconds(1000)) };
            animation.EnableDependentAnimation = true;
            Storyboard.SetTarget(animation, slide);
            Storyboard.SetTargetProperty(animation, "(SlideTranslate.Y)");
            Storyboard sb = new Storyboard();
            sb.Children.Add(animation);
            sb.Begin();

 

 

posted @ 2012-12-07 13:49  农村山沟沟出来的大学生  阅读(979)  评论(0编辑  收藏  举报