WPF/Silverlight深度解决方案:(一)解锁被Storyboard束缚的关联属性

原文 WPF/Silverlight深度解决方案:(一)解锁被Storyboard束缚的关联属性

如果您在使用WPF/Silverlight进行相关动画开发中使用了Storyboard,并对关联属性进行了动画修改,那么您是否有注意到这些关联属性常常无法再通过直接赋值的形式去修改,尽管它的值已经被更改,但却始终无法在界面上得以体现。例如,在我的C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial)教程里大量运用了Storyboard对角色的X,Y坐标关联属性以及角色Direction朝向关联属性进行动画形式修改;如果统一的每次更改均使用Storyboard是不会存在任何问题的,结果是所见即所得。但是如果大家在使用Storyboard更改了朝向Direction这个关联属性后,若想通过鼠标右键点击然后再更改角色朝向朝北:Direction = 0,结果却无任何效果;很多朋友怀疑:是不是鼠标右键事件哪个位置写错了?结果却并非如此。在WPF/Silverlight中使用Storyboard修改过关联属性后,这些关联属性将被锁定,外界是无法通过直接赋值的形式对其进行修改的。难道束手无策了?其实msdn很早就给我们提供了3个解决方案,原文地址:

http://msdn.microsoft.com/zh-cn/library/aa970493.aspx

下面是我对它们的解析及拓展:

方法一:将动画的 FillBehavior 属性设置为 Stop:

storyboard.FillBehavior = FillBehavior.Stop;

通过将FillBehavior设置为Stop,即通知动画在到达其活动期末尾后停止影响其目标关联属性。虽然达到了目的,但必须等待动画结束时才会生效,且更关键的是之前被storyboard修改过的所有关联属性值此时都被还原成了初始值。因此,此方法只适合用于制作类似网页中的导航菜单按钮:当鼠标悬停在菜单上时,菜单图形按钮执行一段华丽的变化动画;当鼠标移开后即变回为初始图片。

方法二:移除整个动画板(Storyboard)。此方法必须通过类似           

Leader.BeginStoryboard(storyboard, HandoffBehavior.SnapshotAndReplace, true);或

storyboard.Begin(Leader, HandoffBehavior.SnapshotAndReplace, true);

这两种方式启动动画,然后在需要解锁时通过

storyboard.Remove(Leader); storyboard = null; 通知动画板动画停止影响名为Leader对象的目标关联属性,并移除storyboard。需要特别注意的是①必须将动画的IsControllable参数设置为true;②HandoffBehavior最好设置为SnapshotAndReplace,此枚举的作用是:新动画将替换它们所应用到的关联属性上的任何现有动画。

方法三:从单个关联属性移除动画。同样的以精灵角色朝向为例,如果该属性已被Storyboard锁定,那么如果此时需要对其值进行更改,我们可以通过类似:

Leader.BeginAnimation(QXSpirit.DirectionProperty, null);或

Leader.ApplyAnimationClock(QXSpirit.DirectionProperty, null);

这两种方法来禁止关联到Leader的动画继续影响Leader的DirectionProperty关联属性(此方法对于非动画板动画也同样有效)。接着后面我们就可以轻松的通过Leader.Direction = 0 为精灵的朝向属性进行赋值并在画面中得到体现。

    以上三种解决方案在WPF中灵活的配合storyboard.Children.Clear();使用几乎可以应付任何关于Storyboard锁死关联属性的问题;但是在Silverlight中却往往不尽如人意。毕竟只是WPF的子集,在功能与方法上有着太少的支持。因此,我拓展了以下两种解决方案,更重要的,它们均为WPF/Silverlight通用的且药到病除的终极策略。

方法四:可以通过每次运行新的动画时先暂停之前的动画(注意,是暂停(Pause)而不是停止(Stop)),例如storyboard.Pause(Leader);然后再创建一个新的动画板storyboard = newStoryboard();这样,之前被storyboard修改过的关联属性目标值会被新的storyboard作为起点属性值,从而完美实现关联属性在动画与动画之间的衔接。有些朋友会问那之前的storyboard是否会继续占用内存空间?对于.net的内存回收机制我们无法控知,根据我多方查阅的资料,若您不放心,不妨在创建新的Storyboard前,通过storyboard = null 将之注销掉,在Silverlight动画中我是这样做的,实践证明此方法确实达到的目的。

方法五:以毒攻毒。既然是Storyboard锁死了我们需要更改的关联属性,那么我们同样可以通过Storyboard动画的形式来赋值更改这些关联属性。此方法乃下下策,缺点是毫无性能而言;优点是万能性:适合一切被Storyboard锁死的关联属性的修改,且无论是在WPF还是Silverlight中。下面同样以精灵的朝向为例,我们可以通过:

DoubleAnimation doubleAnimation = new DoubleAnimation();

doubleAnimation.To = direction;

doubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(10));

Storyboard.SetTarget(doubleAnimation, spirit);

Storyboard.SetTargetProperty(doubleAnimation, newPropertyPath("Direction"));

storyboard.Children.Add(doubleAnimation);

storyboard.Begin();

这样的动画形式对QXSpirit.DirectionProperty关联属性进行强行更改。

      本节小结:希望以上5种解锁Storyboard关联属性的解决方案能对大家的WPF/Silverlight动画开发有所帮助;同时,如果哪些地方有写得不妥或有错漏的也请大家不吝赐教,我会及时进行修改及更正。

下一节我将为大家讲解如何保护Silverlight源码,敬请关注。

作者:深蓝色右手

出处:http://blog.csdn.net/alamiye010/

本系列目录及源码下载:点击进入

本文版权归作者和CSDN共有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面显著位置给出原文连接,否则保留追究法律责任的权利。

时间: 2024-11-10 00:50:48

WPF/Silverlight深度解决方案:(一)解锁被Storyboard束缚的关联属性的相关文章

一起谈.NET技术,WPF/Silverlight深度解决方案:目录

介于目前WPF/Silverlight技术资料在国内相当稀缺,仅有的也是一些很基础的教程.为了更深度的剖析WPF/Silverlight的技术内涵,解决开发过程中的疑难杂症,分解实际应用案例的特色细节,"WPF/Silverlight深度解决方案"系列由此孕育而生.整个系列的所有文章均为原创,由本人的个人开发经验结合相关资料编写而成,过程中难免有错漏或不妥当的地方还望各位读者友善的指出.我们的目标只有一个:WPF/Silverlight技术深度挖掘.如果您有符合本系列主题的内容想要与大

WPF/Silverlight深度解决方案:目录

介于目前WPF/Silverlight技术资料在国内相当稀缺,仅有的也是一些很基础的教程.为了更深度的剖析WPF/Silverlight的技术内涵,解决开发过程中的疑难杂症,分解实际应用案例的特色细节,"WPF/Silverlight深度解决方案"系列由此孕育而生.整个系列的所有文章均为原创,由本人的个人开发经验结合相关资料编写而成,过程中难免有错漏或不妥当的地方还望各位读者友善的指出.我们的目标只有一个:WPF/Silverlight技术深度挖掘.如果您有符合本系列主题的内容想要与大

C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四十一)

C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四十一)制作精美的Mini地图① 用什么来承受未来几个月日思夜想的折磨?除了学习还是学习. 感慨了一翻,嘿嘿.本节我将为大家讲解如何为Silverlight游戏制作一个精美的Mini地图.Mini地图又分两种,一种是通常处于游戏窗口右上角的Mini雷达(导航)地图:另一种是全景Mini寻路地图.本节我先向大家讲解如何制作导航Mini雷达地图.此类地图在游戏中主要起到导航作用,即引导主角前行的方向,并且呈现出

C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(八)

C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(八) 完美实现A*寻径动态动画 本节将紧接着上一节,在它的基础上实现鼠标点击动态创建完美的A*寻路动画.(模拟游戏中人物的真实移动,这次可是有障碍物的,可以说基本上完成了人物移动引擎的一半了呢) 首先,在上一节的代码前部分加入一个叫做player的圆形作为我们将要控制的对象(模拟游戏中的主角,下文均称之为"主角"): Ellipse player = new Ellipse(); //用一个圆来模拟目

C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(一)让物体动起来①

序:自从QXGame(WPF GAME ENGINE)游戏引擎公布以来,受到很多朋友的热切关注,于是乎有了写教程的想法.那么从今天开始,我将带领大家一步一步的学会如何使用纯C#开发WPF/Silverlight游戏引擎,过程中我会尽量的开源,并对相关小技巧进行解释和介绍,比较复杂的算法原理我会给大家一条绝对可行的思路,至于如何处理这些复杂的算法,那是仁者见仁,智者见智了,或许您写的算法比我的更好呢. 多余的话不多说了,最后来句发自肺腑的话吧:本系列教程的书写编辑花费作者很多心血,没有功劳也有苦劳

C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四十)

C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四十)向Silverlight移植② 三.新增功能: 1)新增游戏的音乐及音效对象: public static MediaElement gameMusic, gameAudio; 2)新增游戏鼠标光标: //设置游戏鼠标光标 GameCursor.Stretch = Stretch.Fill; GameCursor.Source = Super.GetImage("/Image/Cursor/0.png

C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(三十九)

C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(三十九)向Silverlight移植① 一.主要改进: 1)Silverlight3.0上的右键实现: //注册右键事件 HtmlPage.Document.AttachEvent("oncontextmenu", Game_MouseRightButtonDown); //鼠标右键事件 private void Game_MouseRightButtonDown(object sender, H

C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(二十九)

C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(二十九) 人工智能(AI)之追踪者 经过前面28节的不断完善,主角已经具备了MMORPG游戏中的大多数功能:但是其他精灵例如怪物等暂时还是无法行动的,上一节中它们无辜的充当了主角的肉靶子,它们开始呐喊:上帝呀,请给予我们灵魂与智慧吧!其实灵魂早就有了,就是精灵的生命线程.那么该如何赋予精灵智慧呢? 精灵智慧的实现其实就是为精灵赋予AI(人工智能).完整的游戏引擎或多或少都必须拥有一定的AI,例如棋牌类型游戏有着

C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(二十二)

C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(二十二)重构 – 让代码插上翅膀自由飞翔 上一节,我将游戏地图模式进行了一次重大的变动,这在实际开发中意味着项目大规模重置,虽然表面上显得游刃有余,仅仅一个AllMove()方法的改变即实现了完美转型,这全得归功于前20节所搭建起的相对高度可扩展平台.但是,随着开发不断深入,我慢慢的感到些许的不安,因为代码上的日益松散与结构的渐渐稀疏如同Windows系统的磁盘碎片与日俱增,未来维护时的烦琐与痛心疾首已历历在目