2012-05-04 8 views
2

私のアプリケーションのモデルでは、それぞれが「子供」のリストを参照する「親」のリストを持っています(例えば、それぞれに選手のリストを含むフットボールのリスト)。コレクションと親子関係のMVVMの概念

このリストをツリービューで表示します。ツリーのビューモデルクラスと、フットボールチームのビューモデルクラス(「footballteamViewModel」と呼ぶ)を作成しました。ツリーのクラスは、footballteamViewModel-itemsを持つObservableCollectionを保持します。ツリーのitems-sourceはObservableCollectionです。初期化中は、モデル内のすべてのフットボールチームに対して対応するfootballteamViewModelオブジェクトを作成し、それをObservableCollectionに追加します。

私のモデルのサッカーチームのリストをツリーの外側から変更でき、ツリーを更新したいことです。だから、モデルの中のリストからサッカーチームを削除した場合、私はfootballteamViewModel-itemsのObservableCollectionで対応するアイテムを削除する必要があります。

私はモデルからサッカーチームのリストをビューに直接バインドできません。だからモデルのコレクションが変更されるたびに、ViewModelでObservableCollectionを何とか更新する必要があります。

これを処理する私のやり方は、ObservableCollectionをモデルで使用し、ViewModelのcollectionChangedイベントに登録して、モデルコレクションが変更されたときにViewModel(Observable Collection of footballteamViewModelオブジェクト)を更新することです。しかし、これは "正しい"と感じません。より良い方法がありますか?

これを入力している間、同じ問題を正確に記述する別の投稿が見つかりました:WPF/MVVM: Delegating a domain Model collection to a ViewModel。そこの答えは、私がこの問題を解決する方法は全く間違っているわけではないが、まだ別の方法があるのだろうかと疑問に思います。

編集:あなたが提供した最初の回答から私は私の質問に明確な答えがないと仮定します。彼らはすべて役に立ちましたので、それらをすべて読む価値があります。私はBindable Linq/Continuous Linq/Opticsフレームワークへの参照で答えをマークしています。なぜなら、それは他の人が私の質問を最もうかがいます。

答えて

1

解決策は間違いではありませんが、BindableLinq、ContinuousLinq、Obticsのように簡単に実装できるライブラリがあります。あなたは彼らについての話を持っていますhere。悲しいことに、それらのどれも今後の発展の余地がないようです。

私の個人的なClinqの経験は優れており、私はまだそれを使用しています。

2

モデルコレクションを直接ビューにバインドすることはできません。つまり、ビューモデルはモデルコレクションに含まれているものをコピーしてObservableCollectionにする必要があります。さらにビューをライブで更新する必要があるモデルコレクションが変更されたとき(モデルがそのような変更をビューモデルに通知する必要があり、ビューモデルがその内部コピーを更新する必要があるとき)。

これはすべて、実際に多くの揺れの部屋を残すことはありません。面白いかもしれない1つのバリエーションは、モデルのコレクションを読み取り/書き込み可能にすることです。この場合、モデルのコンシューマは、コレクションを変更する必要があるときはいつでも、新しいインスタンスとスワップする必要があります。代わりに、ビューモデルの「同期をとる」コードを簡略化することができ、コレクションプロパティのINotifyPropertyChangedによって同期をトリガーすることができます。

3

これは、MVVMのより厄介なスポットの1つです。私はしばらく前に行っている

ことの一つは、ObservableCollection<T>を継承し、そのような両方のコレクションに対して操作を実行する改質剤のメソッド(削除、追加)を、持っていViewModelCollection<T>を作成します

public interface IViewModel<T> 
{ 
    T WrappedModel { get; } 
} 

public class ViewModelCollection<T,M> : ObservableCollection<T,M> where T : IViewModel<M> 
{ 
    private IList<M> _baseCollection; 

    public ViewModelCollection(IList<T> baseCollection) 
    { 
     _baseCollection = baseCollection; 
    } 

    public override void Add(T objectToAdd) 
    { 
     IViewModel<M> vm = objectToAdd as IViewModel<M>; 
     if (vm != null) 
     { 
      this.Add(objectToAdd); 
      _baseCollection.Add(vm.WrappedModel); 
     } 
    } 

    public override void Remove(T objectToRemove) 
    { 
     IViewModel<M> vm = objectToRemoveas IViewModel<M>; 
     if (vm != null) 
     { 
      this.Remove(objectToRemove); 
      _baseCollection.Remove(vm.WrappedModel); 
     } 
    } 
} 

今では私はドンこれをまったくやってはいけません、私はちょうど私のモデルにINotifyPropertyChanged機能を追加するCastle Proxiesを使っています - 定型コードをたくさん保存します!

私はコードをテストしておらず、ちょうどメモリからそれをタイプダウンしました。後期

1

が、他の皆さんを助け...

は、このトピックについては、この優れた3パートのブログ投稿シリーズを読むことができます。
パート3は、コレクションについてであり、いくつかの解決策を示している - 著者はMVVMについて混乱で、思わ - 私は人々が** **そのブログ記事を読んでいないことを示唆している

MVVM: To Wrap or Not to Wrap? How much should the ViewModel wrap the Model?

+0

私に多くのことができますデータエンティティがモデルであると考えること。または、彼は自分自身を説明することにちょうど悪いかもしれません。 VM内のデータエンティティのラッピングは、コレクション内のプロパティ通知とはほとんど関係のない特定の状況で行われます。 – slugster

+0

彼はこの記事で説明したタスクを達成する3つの方法を示しています(blinq/clinq/self coded)。 – Radioactive