先看一段代码,本文所有的例子,都是在这段代码的基础上进行的.
一个矩形rec,放到布局容器内,这个矩形就是被动画控制的对象,一个double类型的动画.
以前我后台写动画,都是通过先给对象注册名称,通过名称,把对象(Rectangle)和动画(DoubleAnimation)通过Storyboard.SetTargetName()关联到故事版(Storyboard).
例:给矩形加一个TranslateTransform,通过控制X属性,使矩形水平位移
这种方式,动画可以动起来.注意最后的Begin()方法,一定要传一个参数,可以是window(this),可以是布局容器Layout,也可以是矩形自身rec.总之一定要传一个参数,不然动画动不起来.
至于为什么,不知道.去查阅MSDN,无果. https://msdn.microsoft.com/zh-cn/library/cc190590(v=vs.95).aspx
然而还有更致命的一个问题是,对动画进行的暂定,继续,停止等后续操作全部无效.调用移除方法Remove(),也不能触发Completed事件.至于为什么,依然不知道.
为了解决这个问题,做了几种情况的总结.
最终的结果都是使用Storyboard.SetTarget()方法代替Storyboard.SetTargetName(),这样还能避免给对象注册无意义的Name,Begin()方法不传参数.这样就能进行暂定,继续,停止等后续操作了,调用移除方法Remove()时,能够触发Completed事件.
1.改变对象的值类型的依赖属性,如Width,Height等,直接把注册名称换成注册对象就可以,其他没什么变化
2.改变对象的引用类型的依赖属性,如转换RenderTransform等,对象要注册矩形rec而不是TranslateTransform,属性路径要按属性路径语法写,而不是new PropertyPath(TranslateTransform.XProperty).可以理解成矩形并没有TranslateTransform.XProperty属性.
属性路径语法请参考: https://msdn.microsoft.com/zh-cn/library/cc645024(v=vs.95).aspx
3.同2,只不过把转换换成了转换组,重点看属性路径语法,这个语法MSDN并没有提到,我是通过试错,试出来的,这个语法很严格,多个或少个括号,括号换个位置,都不行
完毕,贴出可以复制的代码吧
private Storyboard m_sb;private void Window_Loaded(object sender, RoutedEventArgs e) { m_sb = Test(); }private void Button_Click(object sender, RoutedEventArgs e) { m_sb.Remove(); }private Storyboard Test() { Rectangle rec = new Rectangle() { Width=50,Height=50}; rec.Fill = new SolidColorBrush(Color.FromRgb(255, 0, 0)); Layout.Children.Add(rec); DoubleAnimation da = new DoubleAnimation(); da.Duration = new Duration(TimeSpan.FromSeconds(2)); da.From = 200; da.To = 50; da.RepeatBehavior = RepeatBehavior.Forever; da.AutoReverse = true; //注册名称方式 //可以动 但Storyboard的Begin()要传一个参数,可以传this或父级 但不可暂定等后续操作 移除Remove()后不触发Completed TranslateTransform tTf = new TranslateTransform(); rec.RenderTransform = tTf; //名称不能以数字开头,不能包含"-" string name = "tTf" + Guid.NewGuid().ToString().Replace("-", ""); this.RegisterName(name, tTf); Storyboard.SetTargetName(da, name); Storyboard.SetTargetProperty(da, new PropertyPath(TranslateTransform.XProperty)); Storyboard sb = new Storyboard(); sb.Completed += sb_Completed; sb.Children.Add(da); sb.Begin(this); return sb; ////1.改变对象的值类型的依赖属性 ////有效 //Storyboard.SetTarget(da, rec);//通过名称注册换成通过对象注册 //Storyboard.SetTargetProperty(da, new PropertyPath(Rectangle.WidthProperty)); ////Storyboard //Storyboard sb = new Storyboard(); //sb.Completed += sb_Completed; //sb.Children.Add(da); //sb.Begin(); //return sb; ////2.改变对象的引用类型的依赖属性 //TranslateTransform tTf = new TranslateTransform(); //rec.RenderTransform = tTf; ////无效 //Storyboard.SetTarget(da, tTf);//转换 //Storyboard.SetTargetProperty(da, new PropertyPath(TranslateTransform.XProperty));//不按属性路径语法 ////无效 //Storyboard.SetTarget(da, rec);//矩形 //Storyboard.SetTargetProperty(da, new PropertyPath(TranslateTransform.XProperty));//不按属性路径语法 ////有效 //Storyboard.SetTarget(da, rec);//矩形 //Storyboard.SetTargetProperty(da, new PropertyPath("(Rectangle.RenderTransform).(TranslateTransform.X)"));//按属性路径语法 ////Storyboard //Storyboard sb = new Storyboard(); //sb.Completed += sb_Completed; //sb.Children.Add(da); //sb.Begin(); //return sb; ////3.转换组,属性路径语法 //TranslateTransform tTf = new TranslateTransform(); //ScaleTransform sTf = new ScaleTransform(); //TransformGroup tfg = new TransformGroup(); //tfg.Children.Add(tTf); //tfg.Children.Add(sTf); //rec.RenderTransform = tfg; ////有效 //Storyboard.SetTarget(da, rec);//矩形 //Storyboard.SetTargetProperty(da, new PropertyPath("(Rectangle.RenderTransform).Children[0].(TranslateTransform.X)"));//按属性路径语法 ////Storyboard //Storyboard sb = new Storyboard(); //sb.Completed += sb_Completed; //sb.Children.Add(da); //sb.Begin(); //return sb; } void sb_Completed(object sender, EventArgs e) { }
View Code
原理依然不清楚,如有大神知道,望指点
如果感觉此文对你有帮助,请点击"推荐"
推荐一个不错的Blend,Wpf,sl交流群
群号码:152049269
欢迎大神,萌新踊跃加入,交流探讨,共同进步!
原标题:对后台代码写动画 出现的一些怪异行为 的总结
关键词: