2012-02-16 21 views
3

MVVMを使用するSilverlightアプリケーションでは、巨大なデータをプロットするグラフ(サードパーティ製ComponentOne)があり、レンダリングに時間がかかります。MVVMでViewModelを一括変更するときに、BeginUpdate/EndUpdateのようなバッチ処理を使用するにはどうすればよいですか?

グラフのデータソースにバインドされているObservableCollection(たとえばchartDataCollection)がViewModelにあります。

一部のシナリオでは、100秒間CollectionChangeイベントを発生させ、時間がかかるたびにチャートをレンダリングする、chartDataCollectionの項目を100個追加します。

私はこれらの更新をまとめてグループ化し、完了したら一度だけUIに通知できますか? BeginUpdateステートメントとEndUpdateステートメントを使用してデータグリッドにデータを追加する際に、WinFormsの世界で使っていたようなものです。

答えて

2

実装するインターフェイスはINotifyCollectionChangedです。このインターフェイスは、WPFバインディングとCollectionChangedイベントを介して通信します。このイベントの引数(NotifyCollectionChangedEventArgs)は、変更されたアイテムのバッチをレポートできます。

これを行う1つの方法は、独自のMyBatchObservableCollecitonを実装して、List(またはその他の適切なコレクション)を派生させるか、(より適切に)組み込むことです。インナーコレクションを変更し、これらの変更をすべて記録するメソッドを実装します。すべての変更をWPFにコミットする準備ができたら、変更のリストを送信してください。ここでは、(あなたのコレクションにfuncitonalityを「追加」のみ実装)行うことができます何のサブセット例です。

class BatchObservableColleciton<T> : INotifyCollectionChanged, IEnumerable 
{ 
    public event NotifyCollectionChangedEventHandler CollectionChanged; 

    private List<T> _list; 
    private List<T> _addedItems; 

    public BatchObservableColleciton() { 
     _list = new List<T>(); 
     _addedItems = new List<T>(); 
    } 

    public IEnumerator GetEnumerator() 
    { 
     return _list.GetEnumerator(); 
    } 

    public void Add(T item) 
    { 
     _list.Add(item); 
     _addedItems.Add(item); 
    } 

    public void commit() { 
     if(CollectionChanged != null) { 
      CollectionChanged(this, new NotifyCollectionChangedEventArgs(
       NotifyCollectionChangedAction.Add, _addedItems)); 
     } 
     _addedItems.Clear(); 
    } 

} 

はそれを自分自身を試したことはありませんが、私はこれは移動するための方法だと思います。 Google for Custom & ObservableCollection。正確ではありませんが、そこには実装がほとんどありません。

0

ObservableCollectionを使用する代わりに、INotifyPropertyChangedパターンを使用する単純なIEnumerableプロパティを使用してください。

private IEnumerable _ChartDataCollection; 
public IEnumerable ChartDataCollection 
{ 
    get 
    { 
     return _ChartDataCollection; 
    } 
    set 
    { 
     if (_ChartDataCollection != value) 
     { 
      _ChartDataCollection = value; 
      NotifyPropertyChanged("ChartDataCollection"); 
     } 
    } 
} 
+0

これは間違った答えです。 IEnumerableに加えて、INotifyCollectionChangedを実装する必要があります。 – Uri

+0

いいえ、動作します。追加/削除するたびにChartDataCollectionプロパティをチャートデータソースにリセットする必要があります。 –

+0

@Uri INotifyCollectionChangedは、OPが持つ問題を表示します。ソリューションが機能している間、それは過度にアーキテクチャされています。私のソリューションは機能し、簡単です。 –

0

すべての変更に別のコレクションを使用して、2つのコレクションをマージしてから、公開コレクションに割り当ててみましょう。これにより、PropertyChangedイベントが1回だけ発生します。

// Create a new List that contains objects from your Collection 
var list = new List<SomeItem>(SomeCollection); 

foreach(var item in newItems) 
{ 
    // Add new items to list 
} 

// Reset collection w/ items from List 
SomeCollection = new ObservableCollection<SomeItem>(list); 
関連する問題