2009-04-26 8 views
5

私は、私のアプリでObservableCollectionsにバインドされたリストボックスをいくつか持っていて、アイテムが削除されているとアニメーション化したいと思います。リストボックスで削除された項目をアニメートする

FrameworkElement.Loadedイベントを使用して追加されたアイテムをアニメーション化することについての質問が既に見つかりましたが、もちろんUnloadedイベントでは同じように動作しません。

これをデータ型で使用できる方法はありますか?

EDIT:ItemsSourceのCollectionChangedイベントに接続し、手動でアニメーションを適用しようとしました。現在、次のようになっています:

ListBoxItem item = stack.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem; 
     item.LayoutTransform = new ScaleTransform(1, 1); 

    DoubleAnimation scaleAnimation = new DoubleAnimation(); 
    scaleAnimation.From = 1; 
    scaleAnimation.To = 0; 
    scaleAnimation.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 500)); 
    ScaleTransform transform = (ScaleTransform)item.LayoutTransform; 
    transform.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation); 

問題は、まったく動作しません。アイテムはまだ飛び去るだけです。メソッドが呼び出されるとアイテムはまだそこにあるので、アニメーションが消える前にアニメーションを再生してはいけませんか?それとも、私はそれを完全に間違っているのですか?

答えて

1

イベントを削除する前に募集していたとしても、瞬時に削除されることが判明しました。だから私は観測可能なスタックとして使用していたので、私はこれを取り除いた要素をコレクションに残して、後で取り除くことでこの問題を解決しました。

public class ObservableStack<T> : ObservableCollection<T> 
{ 
    private T collapsed; 
    public event EventHandler BeforePop; 

    public T Peek() { 
     if (collapsed != null) { 
      Remove(collapsed); 
      collapsed = default(T); 
     } 
     return this.FirstOrDefault(); 
    } 

    public T Pop() { 
     if (collapsed != null) { Remove(collapsed); } 
     T result = (collapsed = this.FirstOrDefault()); 
     if (BeforePop != null && result != null) BeforePop(this, new EventArgs()); 
     return result; 
    } 

    public void Push(T item) { 
     if (collapsed != null) { 
      Remove(collapsed); 
      collapsed = default(T); 
     } 
     Insert(0, item); 
    } 
} 

ベストソリューションではないかもしれませんが(少なくとも私はスタックとしてのみ使用しています)ジョブを実行します。

+0

私の場合は、Obpertによって実装された3dparty INotifyCollectionChangedがあり、時にはサーバー側のイベントによって変更されています...ここでアイテムのアニメーションをどのようにアニメーション化するかわからない...おそらくカスタムINotifyCollectionChangedでラップし、アニメーション。しかし、これはイベントごととアニメーションごとに1つのアイテムに対してのみ機能します。 INotifyCollectionChangedコントラクトは、すべてのインスタンスがイベントによってすぐにコレクションを変更することを前提としています。遅延がある場合、次のイベントは、以前のインデックスでコレクションを保持していると仮定して、 –

1

現時点ではコードウィンドウにアクセスできないので、これは袖口から少し外れていますが、UnloadingイベントでFrameworkElementを拡張し、ObservableCollectionのCollectionChangedから開始することができます。これはカスタムObservableCollecitonとカスタムFrameworkElementクラスを使用することを意味しますが、必要なものを提供できますか?

+0

既にUnloadイベントがあります。しかし、とにかくこれは要素の存在の最後の手段であり、このイベントが発生した後にアニメーション化するものはないので、アニメーションにとっては役に立たない。 –

1

Present.Commands Fluent APIを使用すると、コマンドの実行中に視覚的な状態を変更できます。 私はhttp://adammills.wordpress.com/2011/01/11/mvvm-animation-of-listbox-present-commands/

+0

これは、ユーザーがこのコマンドをトリガーする場合の解決策です。私の場合、私はInotifyCollectionChangedをObticsで実装し、サーバー側で変更しました...ここでアイテムの削除をアニメーション化する方法はわかりません... –

2

ここでそれを使用して、リストボックス内の項目の追加や削除 のアニメーションの例を掲載している私はバインド項目にIsRemovedプロパティを追加することでこれを解決しました。 ListViewItemコンテナテンプレートのイベントトリガーがバインドされ、このブールがtrueに変更されたときに削除アニメーションが再生されます。同時に、Task.Delay(n)はアニメーションの継続時間と一致して開始され、実際のコレクションから削除されます。この削除は、スレッド間の例外を避けるためにリストを所有するスレッドにディスパッチする必要があることに注意してください。

void Remove(MyItem item, IList<MyItem> list) 
{ 
    item.IsRemoved = true; 

    Task.Factory.StartNew(() => 
     { 
      Task.Delay(ANIMATION_LENGTH_MS); 
      Dispatcher.Invoke(new Action(() => list.Remove(item))); 
     }); 
} 
関連する問題