ビューをモデルプロパティにバインドする必要がありますか、それともViewModelがそれを所有する必要がありますか?


21

私は次の技術環境でプロジェクトを開始しています:.Net 4.0、Entity Framework 4.0、WVM with MVVM Architecture

私はネット上で多くの例を見て、この環境に関する本をいくつか見ました。いくつかの例では、著者はこのアイデアを持っていました:

  1. Viemodelには、Modelクラスのインスタンス(Entity Framework Entity、Personなど)があります
  2. WPFビューコントロールをModelのプロパティにバインドします

一部の著者はそうしましたが:

  1. Viemodelは、モデルのすべてのプロパティを公開します。
  2. モデルに直接ではなく、ViewModelのプロパティにWPFビューコントロールをバインドします。

それでは、viewmodelが独自のモデルを公開するのではなく、モデルからプロパティをバインドできるようにすることをお勧めしますか?またはどちらがより好ましいですか?


個人的には、モデルのプロパティを公開すると、データレイヤーとロジックレイヤーが適切に分離されます。
アレックスホープオコナー

回答:


25

多くのプログラマーは、最初にモデルに直接バインドするショートカットを最初にしようとすると思いますが、私の経験ではこれにはいくつかの大きな欠点があります。主な問題は、エンティティモデルがNHibernateまたは同様のものによって永続化されている場合、ビューがモデルプロパティを更新するとすぐに、NHibernate それらの変更をデータベースに永続化できることです。Save / Cancelボタンがある編集画面ではうまく機能しません。実際には、すべてをバッチとして待機して保持することを選択する場合がありますが、アイデアは、モデルを変更すると、変更をコミットするということです。

そのため、読み取り専用画面上のモデルプロパティに直接バインドすることはできますが、矛盾が発生します。

さらに、ほとんどのモデルは実装されINotifyPropertyChangedていないため、最初の表示後に画面の状態が変化した場合、適切なバインディングターゲットではない可能性があります。

自動プロパティの容易さを考えると、モデルではなくViewModelに常にビューをバインドすることをお勧めします。一貫性があり、シンプルで、将来の変更をサポートするための最も柔軟性があります。


あなたの答えが好きです。編集/保存画面に言及するための+1 ..しかし、その後、モデルに1回、ビューモデルに1回、プロパティを2回記述するのは困難です。また、開発時間も長くなります。そうすることは正当であると思いますか...?
プラビンパティル

9
@Pravin Patil-ちょっと、そのショートカットをとるたびに、後で戻って修正しなければならなくなったときに自分を呪った。ViewModelでプロパティを再実装するのは、特に読み取り専用の場合は比較的簡単です(自動実装されたプロパティをプライベートセッターで使用できるため)。実際、ほとんどの場合、モデルはViewModelとは異なるデータ構造です。ビューに影響を与えずにモデルを変更できる柔軟性を残してください。ビューをテストするのは難しいため、ビューを変更する必要が少ないほど良いです。
スコットホイットロック

4
@Scott Whitlock:私は2年前からNHibernateを使用してWPFアプリケーションを開発してきましたが、モデルに直接バインドしてもまったく問題はありませんでした。実際、モデルのプロパティが変更されると、バインドする対象に関係なく、ほとんど変更と同じ労力がかかります。また、後でViewModel自体でルーティングを行う必要がある場合、必要になるまで時間をかける価値はありませんでした。私はYAGNI(まだ)アプローチを採用しており、問題はありません。あなたとここにいる他の人たちは、この問題について少し独断的になっていると思います。
ファルコン

16

aのポイントViewModelは、それがのモデルであることViewです。

あなたは結合しなければならないViewModelViewではなく、任意のModel(直接ではなく、とにかく)の特性。


8

両方の方法が受け入れられると思う

ViewModelのみにバインドするのが「MVVM-purist」アプローチであり、レイヤー間の分離が改善されます。通常、モデルへのバインドはより高速で便利です。

レイヤーを完全に分離する正当な理由がない限り(プロジェクトのサイズ、将来のメンテナンスの問題、使用しているモデルの種類など)、モデルにバインドします。


7

あなたが見ているのはバインドスルーと呼ばれる概念です。つまり、モデルにnameというプロパティがあり、ビューモデルが追加の編集や変換を行わずにこのプロパティを公開している場合、モデルにバインドすることができます

擬似コード:

 {Binding: MyViewModel.MyModel.Name}

これは、ビューモデルの「Fluff」プロパティの量を減らすために行われますが、残念ながら長期的には悪い考えです。ビューモデルの概念は、ビューがモデルに依存しないようにすることです。バインドすることにより、モデルにnameというプロパティが含まれていることを確認する必要があります。そうしないと、実装が中断します。

ただし、view-modelに限りバインドする場合は、モデルを変更できます。view-modelのNameという名前のプロパティのみが表示されるため、ビューは認識できません。

これは、モデルがインターフェイスに基づいている特定の状況でこれを緩和できます。そのため、インターフェイスにプロパティModuleNameを公開するIBaseDetailsがある場合、次のことができます。

擬似コード:

 {Binding: MyViewModel.MyModel.ModuleName}

作成するモデルのいずれかがIBaseDetailsインターフェイス(ゴールデン)を満たす限り、これはエッジケースであり、一般に、カバーするモデルの周りにビューモデルをラップする方が常に90%優れていることに注意してください。


2

Model-> ViewModelから行こうとすると多くの摩擦が見られる場合は、AutoMapperのようなものを試してください。プロパティを手動でコピーすることに関連する退屈な作業を取り除きます。


1

同じ疑問を抱いていたからといって、モデルにではなくビューモデルに常にバインドすると確信しました。

角度反応型のアプローチを取ります。ビューモデルの情報を使用してフォームグループを作成しますが、後でフォームにアクセスする必要があります。値を取得してコピーする値は、自動マッパーまたは手動を使用してモデルに値を実行しますビューモデルのプロパティに入札することほど美しいことはないと思います。たとえば、プロジェクト名があるプロジェクトビューページがあるとします。クライアント名など

プロジェクトにはクライアントがあるため、プロジェクトとクライアントの間には関係があります。そのため、このレベルでは、ビューにプロジェクト名とクライアント名を視覚的に表示するだけでよいので、ビューモデルのプロジェクト名とクライアント名に2つのプロパティを設定して、それらは、後でモデルの構造から取得するコードビハインドのプロパティに値を与えることを心配します。

同じことは、保存/キャンセルの場合にモデルを更新することであり、これ以上クリーンなものはありません。


この投稿は読みにくい(テキストの壁)。それをより良い形に編集してもいいですか?
-gnat

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.