2009-07-11 10 views
27

説明する最良の方法は、とても一例である:MVVM:VMオブジェクトはMオブジェクトを直接公開するか、またはMのゲッターに委譲するゲッターを介してのみ公開しますか?

これはこれは私の質問があるビューモデル

public class PersonVM 
{  
} 

あるモデル

public class Person 
{ 
    public int age; 
    public string name; 
} 

です:
VMが公開する必要があります個人をデータテンプレートに追加するか、モデルプロパティを自分のプロパティでカプセル化しますか?

+0

これらの単純なシナリオでは、ビューモデルを持つという利点はありません。あなたがアンドゥ機能などを実装したいと言うなら、そのロジックはVMに入り、モデルプロパティをラップします。 – rolls

答えて

18

ビューモデルは、独自のプロパティを宣言して、モデルの詳細をビューから隠す必要があります。これにより、柔軟性が最大限に高まり、ビューモデルタイプの問題がモデルクラスに漏れるのを防ぐことができます。通常、ビューモデルクラスは委任によってモデルをカプセル化します。例えば、

class PersonModel { 
    public string Name { get; set; } 
} 

class PersonViewModel { 
    private PersonModel Person { get; set;} 
    public string Name { get { return this.Person.Name; } } 
    public bool IsSelected { get; set; } // example of state exposed by view model 

    public PersonViewModel(PersonModel person) { 
     this.Person = person; 
    } 
} 

は覚えておいてください:このモデルは、それを消費しているビューモデルについて何も知らないはず、とビューモデルは、それを消費しているビューについては何も知りません。バックグラウンドで潜んでいるモデルについては、このビューは何も知らないはずです。したがって、ビューモデルのプロパティの背後にモデルをカプセル化します。

+0

PersonViewModelクラスには、PersonModelパラメータを持つパブリックコンストラクタがあります。だからビューは、ビューモデルをインスタンス化するモデルを知っている必要があります...それはmvvmではありません。コンストラクタは内部的なものでなければならず、文字列のような一般的なパラメータだけを取って、モデルをインスタンス化する必要があります。 –

+0

モデルの値をUIで変更するとします。その結果、モデルはいくつかの他の値も変更します(依存するため)。 OnPropertyChangedHandlerを起動し、VMに独自のプロパティを更新させますか?これは私がやったことです、それはうまくいきますが、私はこのことを初めて知っています。 – rolls

+0

上記のコメントを再入力してください。この記事は私が行ったことを正確に実装しているようです。 https://msdn.microsoft.com/en-us/magazine/ff798279.aspx – rolls

31

この質問に関する一般的な合意はありません。例えば、それはウォードベルhereによって策定MVVMに関する未解決の問題の一つであった:

VMがVに(例えば、生 従業員) 開封されたM-物を提供することができますか?またはMオブジェクトの プロパティ( にもプロパティが許可されている場合でも) がVMラッパー の表面を介して排他的に公開されている必要がありますか?

直接VMにモデルを露出していないの主な利点は以下のとおりです。

  • ビューのために便利な方法でモデル値をフォーマットする、「ステロイドコンバータ」として使用することができます

  • あなたがdata validation messagesundo redo ..

のように、ユーザーインターフェースに関連する他のfuncionalityを注入することができます

短所は以下のとおりです。

  • あなたがのviewmodel内のすべてのモデルのプロパティを公開するために多くのコードを複製する必要があります。

  • ビューコントロールをviewmodelsプロパティにバインドすると、viewmodelからpropertyChangedイベントが送信されます。しかし、モデルプロパティがビューモデルセッターとは異なる他のソースから変更されるとどうなりますか?次に、ViewModelに通知して、OnPropertyChangedを2つ、モデルに1つ、viewmodelに1つと終了させる必要があります。かなり複雑です!

私にとって正しい答えは、あなたの要件によって異なります。

+1

問題の単純な解決策があり、追加するすべての機能を備えたビューモデルをプロキシにする –

+0

これは、モデルを「ラップ(Wrap)」してより多くの機能をトップに注入するのに良い時期です。 – rolls

5

任意のモデルのViewModelを持つことは、それより悪い可能性があります。モデル、または単純なコレクションの階層構造を持っている場合はどうなりますか? その場合は、すべてのモデルを反復処理し、モデルごとにViewModelインスタンスを構築し、通知変更イベントやその他のイベントを登録する必要があります。 IMHO、これは完全に狂気で、不合理です。 DaniCE氏によると、多くのコードと大きな頭痛に終わるでしょう。

+1

私はあなたに同意します、今は何ですか? – Shimmy

+0

既存のModelツリーをVMにラップするのは、比較的単純な前進プロセスです。それを行うユーティリティを作成するか、独自の基本VMクラスに組み込む方がよいでしょう。はい、VMをセットアップしてビューに結合するのに複雑さが増しますが、それは価値があります。その結果、ビジュアルツリーの各レベルでスマートなコード要素が得られます。ビジュアルツリーを検索して操作を処理する人を探す必要はありません。 –

+1

私は、MVVMまで視覚的なヒットテストなしで個々のListBoxItemsで複雑な操作を処理する良い方法を見いだすことはありませんでした。 VM階層を構築し、各VMに適切な参照が与えられると、ListBoxItemsには独自の複雑な操作を実行するために必要なものすべてが用意されています。 –

5

これに対する興味深いソリューションは、MSDNのボリュームにロバート・マッカーターによって提案された25

http://msdn.microsoft.com/en-us/magazine/ff798279.aspx

彼はモデルのすべてをプロキシ回避しながら、モデルの上に層を提供するために、動的なビューモデルを使用していますプロパティ。

問題のスペースに高性能が必要ない場合(ダイナミックではパフォーマンスが低下します)、これは優れたソリューションです。ビューはモデルについて何も知る必要はありませんが、ビューモデルは提供されているプロキシプロパティをそのまま使用する必要はありません。いつでもView Modelにプロパティを追加して、ViewまたはModelを変更せずにModelプロパティをラップすることができます。詳細は記事をお読みください。

+0

または、両方の世界の中で最高のものを使用する...動的ベースのView Modelクラスと非動的ベースのView Modelを定義する。高性能ビューモデルには非動的、他のすべてには動的基本クラスを使用します。 –

+0

DLRはSilverlightでサポートされていないことに注意してください。 '( 私はプロキシプロパティも嫌いです。 – Shimmy

+0

@Shimmy:これは驚くべきことではありません。 –

関連する問題