如何刪除XAML中的故事板(即DataTrigger中的RemoveStoryboard操作),但保留動畫的值。類似於Animatable.BeginAnimation:刪除故事板但保持動畫值?
如果動畫的BeginTime爲空,則將刪除任何當前動畫並且該屬性的當前值將被保留。
如何刪除XAML中的故事板(即DataTrigger中的RemoveStoryboard操作),但保留動畫的值。類似於Animatable.BeginAnimation:刪除故事板但保持動畫值?
如果動畫的BeginTime爲空,則將刪除任何當前動畫並且該屬性的當前值將被保留。
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並保持你的價值,你將需要我上面寫的代碼或類似的東西。
我在使用AnimationTimeline
時遇到類似問題。最簡單的解決方案竟然是在後面的代碼中捕獲Completed
事件,並在調用BeginAnimation
和null
參數之前捕獲動畫,獲取屬性的當前值並使用它來設置它。
這會得到最後的動畫值,並設置它。
void OnCompleted(object sender, EventArgs args)
{
// Required to copy latest animated value to local value.
o.SomeValue = o.SomeValue;
o.BeginAnimation(SomeClass.SomeValueProperty, null);
}
正如我在我的問題中提到的,我想在XAML中提到它。這裏的主要目標是基於以當前值開始的DataTrigger開始新的動畫。 AFAIK,據我所知暫停或停止當前的故事板是無法實現的,因爲它會保留或重置當前值。 另請注意,您的代碼在WPF中不需要。您可以使用BeginTime設置爲null的動畫簡單地調用Animatable.BeginAnimation。它將具有相同的效果,該值被複制到本地。 – bitbonk 2009-11-06 07:53:31
我不確定我瞭解你的需求。如果你只是想開始一個新的動畫,爲什麼不直接調用RemoveAnimation動作呢? WPF旨在從這種情況下的當前值開始。它不是這樣嗎? – 2009-11-06 17:27:42
使用BeginTime = null調用BeginAnimation與我的代碼具有相同的效果是不正確的。特別是,它不會將值複製到本地。如果使用BeginTime = null調用BeginAnimation,然後再調用RemoveAnimation,則值將恢復爲原始值,因爲本地值從未更改過。但是如果你使用我的代碼,這些值將被粘住,因爲它們實際上被複制到本地。我解釋了甚至在RemoveAnimation之後獲得本地值的必要條件,並且像我寫的IS那樣的代碼是必需的。那有意義嗎? – 2009-11-06 17:31:27