WPF: StoryboardにBinding

DoubleAnimationとかでFrom, To, Durationなどを状況に応じて変更させるためにこれらにBindingを設定したいという状況は少なくないと思うのですが、ControlTemplate.TriggersやStyle.Triggers内で定義すると実行時に”Cannot freeze this Storyboard timeline tree for use across threads”なるメッセージの例外が出ます。

どうもはっきり理解できていないのですが、理由は以下のどちらかかな?
  • Animationやっている最中にFrom, To, Duration値が変えられると困る。なので少なくともStoryboard開始前にはこの値を固定(Freeze)する必要がある。値を動的に変えることが目的のBindingはこれに反する。
  • TemplateやStyleは使いまわされることが前提なので、事前(多分Exe実行初期)にXamlをコンパイルしてパフォーマンスを改善している。よってコンパイル後値が変わる要因となるBindingは認められない。

ここの例Link はStoryboardをリソース指定、開始をコードビハインドでやることで、うまく回避できているということでしょうか。Animation開始後にウィンドウサイズを変えてもボールの動きが追従しないので、Animation中は値が変えられないということがわかります。

コードビハインドで取得したリソースはDynamicResourceに相当するLink らしいので、Storyboardをリソースで指定してDynamicResourceで参照すればと試したのですが、少なくともControlTemplateではうまく行かず。

[参考]

[2013/3/18 追記] 結局プロパティの変化を捕まえて、毎回コードビハインドでStoryboardから作る方法で逃げた

Storyboard LastStoryboard;
double from, to;

void BeginHeightAnimation()
{
    if (LastStoryboard != null) LastStoryboard.Stop();

    ControlTemplate template = (ControlTemplate)GetValue(TemplateProperty);
    FrameworkElement target = (FrameworkElement)template.FindName("Target", this);
    DoubleAnimation dblAnim = new DoubleAnimation(from, to, new Duration(TimeSpan.FromMilliseconds(200)));
    Storyboard sb = new Storyboard();
    sb.Children.Add(dblAnim);
    Storyboard.SetTarget(dblAnim, target);
    Storyboard.SetTargetProperty(dblAnim, new PropertyPath(FrameworkElement.HeightProperty));

    sb.Begin();

    LastStoryboard = sb;
}

— posted by mu at 12:31 pm  

T: Y: ALL: Online:
ThemeSwitch
  • Basic
Created in 0.0096 sec.
prev
2013.3
next
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31