若是您在使用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
下面是我對它們的解析及拓展:html
方法一:將動畫的 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 = new Storyboard();這樣,以前被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, new PropertyPath("Direction"));
storyboard.Children.Add(doubleAnimation);
storyboard.Begin();這樣的動畫形式對QXSpirit.DirectionProperty關聯屬性進行強行更改。