如何用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();