2009-11-05 44 views

回答

4

RemoveStoryboard的主要用途是刪除動畫值並將其設置回其未動畫狀態。在大多數情況下,您可以將呼叫切換到PauseStoryboard或StopStoryboard,具體取決於具體情況。唯一的例外是當你需要釋放故事板中的資源或將其用於其他目的時。

如果您確實要刪除故事板並保留屬性值,則必須直接在屬性上設置動畫值。這可以通過每個值設置爲動畫值,像這樣做:

void CopyAnimatedValuesToLocalValues(DependencyObject obj) 
{ 
    // Recurse down tree 
    for(int i=0; i<VisualTreeHelper.GetChildrenCount(obj); i++) 
    CopyAnimatedValuesToLocalValues(VisualTreeHelper.GetChild(obj, i)); 

    var enumerator = obj.GetLocalValueEnumerator(); 
    while(enumerator.MoveNext()) 
    { 
    var prop = enumerator.Current.Property; 
    var value = enumerator.Current.Value as Freezable; 

    // Recurse into eg. brushes that may be set by storyboard, as long as they aren't frozen 
    if(value!=null && !value.IsFrozen) 
     CopyAnimatedValuesToLocalValues(value); 

    // *** This is the key bit of code *** 
    if(DependencyPropertyHelper.GetValueSource(obj, prop).IsAnimated) 
     obj.SetValue(prop, obj.GetValue(prop)); 

    } 
} 

調用此對你之前刪除故事板複製的動畫值。

編輯有人評論說這段代碼可能是不必要的,因爲調用BeginTime = null的BeginAnimation可以達到類似的效果。

雖然BeginAnimation和BeginTime = null使得它看起來好像這些值被複制到本地,但是稍後調用RemoveStoryboard將導致值恢復。這是因爲使用BeginTime = null的BeginAnimation會導致先前的動畫在新動畫開始之前保留其值,但不影響本地值。

上面的代碼實際上覆蓋了局部值,所以所有的動畫都可以被刪除,對象仍然會有新的值。所以,如果你真的想調用RemoveStoryboard並保持你的價值,你將需要我上面寫的代碼或類似的東西。

+0

正如我在我的問題中提到的,我想在XAML中提到它。這裏的主要目標是基於以當前值開始的DataTrigger開始新的動畫。 AFAIK,據我所知暫停或停止當前的故事板是無法實現的,因爲它會保留或重置當前值。 另請注意,您的代碼在WPF中不需要。您可以使用BeginTime設置爲null的動畫簡單地調用Animatable.BeginAnimation。它將具有相同的效果,該值被複制到本地。 – bitbonk 2009-11-06 07:53:31

+0

我不確定我瞭解你的需求。如果你只是想開始一個新的動畫,爲什麼不直接調用RemoveAnimation動作呢? WPF旨在從這種情況下的當前值開始。它不是這樣嗎? – 2009-11-06 17:27:42

+0

使用BeginTime = null調用BeginAnimation與我的代碼具有相同的效果是不正確的。特別是,它不會將值複製到本地。如果使用BeginTime = null調用BeginAnimation,然後再調用RemoveAnimation,則值將恢復爲原始值,因爲本地值從未更改過。但是如果你使用我的代碼,這些值將被粘住,因爲它們實際上被複制到本地。我解釋了甚至在RemoveAnimation之後獲得本地值的必要條件,並且像我寫的IS那樣的代碼是必需的。那有意義嗎? – 2009-11-06 17:31:27

1

我在使用AnimationTimeline時遇到類似問題。最簡單的解決方案竟然是在後面的代碼中捕獲Completed事件,並在調用BeginAnimationnull參數之前捕獲動畫,獲取屬性的當前值並使用它來設置它。

這會得到最後的動畫值,並設置它。

void OnCompleted(object sender, EventArgs args) 
{ 
    // Required to copy latest animated value to local value. 
    o.SomeValue = o.SomeValue; 
    o.BeginAnimation(SomeClass.SomeValueProperty, null); 
}