15

MVVMパターンに従うWPFアプリケーションがあります。これまでのところ、アプリケーションは2つのビューとビューモデルを定義しています。

  • LoginView(モデル)
  • ProjectsView(モデル)

両方のビューモデルは、他のビューモデルからいくつかのプロパティにアクセスする必要があります。

例:
LoginViewModelプロパティがありますProjectListProjectsViewModelこのプロパティにもアクセスする必要があります。

これは単純な例にすぎません。後で、UserControlsすべてが互いに相互作用する必要があるいくつかがあります。

UserControlsすべての(ビュー)が設定された1つの巨大なビューモデルを作成する方がよいでしょうDataContextか?そうでない場合、すべての異なるビューモデルはどのように相互作用できますか?

備考:
この質問はこれと密接に関連していますが、アプローチが異なります。

4

5 に答える 5

50

巨大な「メインビューモデル」を作成しないでください。これは、神オブジェクトと似ていないアンチパターンです。

ここでの重要なアイデアは、ビューモデルが他のビューモデルからいくつかのプロパティにアクセスする必要がないということです。むしろ、すべてのビューモデルは特定の情報にアクセスする必要があります。

現在、インスタンス化時にこの情報を各ビューモデルに挿入している可能性があります。これを行う代わりに、各ビューモデルにサービスへの参照を提供します。これは、プロパティやメソッドを通じてこの情報を公開するアプリケーションモジュールです。情報は、本質的に非常に単純な場合はスカラー値の形式で、それよりも複雑な場合はモデルの形式で公開できます。

概略的には、これは次のようになります。

/--------------\
|  ViewModelA  |
|              | <=======\
|              |         |
\--------------/         |  <--- information is pulled      /================\
                         +=========[model]===[model]======  |    Service     |
/--------------\         |                                  \================/
|  ViewModelB  |         |
|              | <=======/
|              |
\--------------/

サービスは、構築時にビューモデルに注入する必要があります(手動で、またはDIコンテナーを使用している場合はDIコンテナーによって)。各ビューモデルは、サービスへの参照と、関心のあるモデルをサービスに伝えるのに十分な情報のみを必要とします。次に、サービスにそのモデルを要求し、それに基づいて「興味深い」プロパティを設定します。

この方法は、単にビューモデルオブジェクトを作成してそのプロパティを外部に設定するよりも複雑ですが、アプリケーションを管理不能にすることなく複雑にすることができます。

たとえば、さまざまなビューモデルにバインドするビューが多数あり、これらのビューモデルが複雑な方法で多数のモデルに依存している場合、正常に機能するには次のようになります。

  1. ビュー/ビューモデルのペアが作成されます
  2. ビューモデルは、サービスから知る必要のあるモデルを要求します。モデルが変更されたことをサブスクライバーに通知するためにサービスが公開するイベントをサブスクライブします
  3. 変更は、データバインドされたコントロールを介してモデルに実行されます
  4. ビューは、ビューモデルで「保存」コマンドを呼び出します
  5. これに応じて、ビューモデルはサービスで「このモデルを保存」メソッドを呼び出します
  6. サービスは情報を保持し、「モデル変更」イベントを公開します(ステップ2を参照)。
  7. 同じモデルに関心のある他のビューモデルは、モデルが変更されたことを認識しており、サービスに新しい状態を問い合わせることができます

これは、すべてがサービスを介してルーティングされる場合に可能です。それ以外の場合はすべての同期を維持するために必要なことを想像してください。対処する唯一の方法は、すべての情報を巨大なビューモデルに入れ、他のすべてからそれを参照することです。ぶさいくな。

于 2013-01-16T15:26:51.083 に答える
5

Usually I do one of 4 things:

  • Make my ViewModels reference each other, and pass the property around. For example, LoginViewModel might set ProjectsViewModel.ProjectList on successful login. How you implement this depends on how your ViewModels are related to each other, and where logical points of connection would be.

  • Make an ApplicationViewModel which manages things like which page is current, and application-wide objects like the current user or current project list. It would handle transferring shared data to the ViewModels that needs it.

  • Use some kind of Event system to broadcast a message anytime an application-wide property changes, and have any ViewModel that's interested subscribe to receive those messages. The message typically contains the new object as well, so anyone subscribed to receive that message type has access to the new object. (I have a brief summary of Event Systems in my blog article Communication between ViewModels with MVVM if you're interested)

  • Depending on if any of the other options work better, I may consider creating a singleton to hold application-wide data instead. For example, if the User is set on Login and is accessed from many of my ViewModels, I may create a singleton to set the user on first login, and then all my ViewModels can access it.

The one thing I would not do is make one big ViewModel holding all available data. ViewModels should only contain the data specific to it.

于 2013-01-16T15:32:38.767 に答える
1

ある種の依存性注入ツールを使用している場合は、それらの値を提供するクラスを注入できます。たとえば、IProjectServiceは、これらの各ビューモデルのプロジェクトのリストを返すことができます。

1つの巨大なビューモデルのアイデアは魅力的に聞こえません。また、互いの公共のプロパティにアクセスすることによるビューモデル間の強力な結合もありません。また、プロジェクトが追加されたときなど、ビューモデル間の相互作用が必要な場合は、発生が予想されるイベントごとにパブリッシュ/サブスクライブモデルを使用します。

于 2013-01-16T15:24:05.150 に答える
1

モデルには、プロジェクトリストなどが含まれている必要があります。または、モデルにアクセスできるようにする必要があります。ViewModelは、単にモデルとビューの間のレイヤーであり、さまざまなモデルオブジェクトをまとめて、ビューが簡単に表示できる形状に成形し、ビューからのコマンドを処理する機会を提供します(それに応じてモデルを変更します)。 )。

于 2013-01-16T15:28:31.160 に答える
1

1つのベースビューモデルを作成し、その中にすべての共通プロパティを保持し、BaseViewModelにシングルトンを作成し、すべてのビューモデルにそのシングルトンプロパティを追加します。すべてのViewmodelが一度に同期されます。

于 2017-03-01T09:19:50.737 に答える