2

いくつかの項目 (エントリ) の概要を示す小さなアプリがあります。概要のリストにあるエントリのタイトルは、エントリのプロパティです。エントリをクリックすると、エントリを編集できるタブのようなものが開きます。エントリを編集して保存すると、次回は概要タブが更新されます。

ここでは、理解を深めるためのモックアップを示します。

アプリは MVVM パターンに基づいています。各ビューには、DataContext として ViewModel があります。各 ViewModel は Model使用し、各 Model にはDatabaseがあります。
概要タブには、独自の View、ViewModel、および Model (ペア) があります。タブも。エントリの各タブは、同じペア (シングルトン インスタンス) を使用します。他のタブが選択されている場合、少数のバインディングのみが更新されます。

私の質問は、タブ間で通信する方法です。

私には2つのアプローチがあります

  • Mediator パターン (Bootstrapper は 2 つの ViewModel をmediatorと結合します)
  • 各モデルは同じデータベースを使用します (モデルはデータベースをリッスンし、ビューモデルはモデルをリッスンします)

しかし、私はこれらのアプローチに満足していません。
モデル間またはビューモデル間で通信する必要がありますか? それとも、これは間違った方法ですか?

アップデート

皆さんの回答に本当に感謝しています。私の意見では、それらのどれも間違っていたり正しいものではありません。どちらのソリューションが自分に合っているかは好みの問題だと思います。EventAggregator パターンがとても気に入っています。これは、PRISMでの EventAggregatorパターンの実装に関するKarl Shifflettによる素晴らしいビデオです 。しかし、それはパターン自体も説明しています。

@Thomas私の意見では、これを1つのViewModelで行うのは悪い解決策です。ViewModel を分離する必要があります。関心の分離に基づく MVVM 。

4

4 に答える 4

2

私にとっては、ビュー モデル間の通信をプログラムする必要がある場合、通常は悪い兆候です。ビューとビューモデルの間で通信を行う必要がある場合もありますが、2 つのビューモデルを接続する必要がある場合は、可能であれば常に 2 つのビューモデルを結合する必要があるようです。

あなたのモックアップで、私は同じ悪い気持ちを感じました. そもそも、タブごとに個別のビュー モデルを用意する必要があるのはなぜですか? あなたの場合、ビューは分離できますが、ビューモデルを分離してもメリットはありません。したがって、2 つのビュー モデルを 1 つに結合することをお勧めします。

于 2013-08-06T22:35:14.363 に答える
2

機能が表示用のモデル データのフォーマットに関連している場合は、ViewModel 間で通信する必要があります。あるモデルから別のモデルにデータを通信している場合は、モデル間で通信します。

具体的な例を次に示しMicrosoft.Practices.Prismます。Visual Studio で直接 NuGet を使用してアクセスできる名前空間には、実際の通信を行うクラスCompositePresentationEvent<T>とともに、 というクラスが含まれています。EventAggregator

アプリケーション全体に共通の場所 (ここでは App.xaml.vb を選択しましたが、スコープが公開されている任意のコード ファイルにすることができ、VB と同様に C# でも機能します)、そのクラスから継承して型を指定することでイベントを定義します。送信するデータに対応する T。たとえば、単純な文字列を含むメッセージを送信する場合は、次のように宣言します。

Public Class MyEvent: Inherits CompositePresentationEvent(Of String) : End Class

Application クラスで、イベント アグリゲーターを定義します。

Public Shared ReadOnly AppEventAggregator As IEventAggregator = New EventAggregator()

これら 2 つの項目を一緒に使用すると、アプリケーション内の任意の 2 つのオブジェクト間でイベントを交換できます。

これにより、アプリケーション全体が というイベントにアクセスできるようになりますMyEvent。メッセージを送信する場所はいつでもMyEvent、その共有Publish(String)メソッドを呼び出します。

Application.AppEventAggregator.GetEvent(Of MyEvent).Publish("This is my event message")

次に、イベントを受け取るには、次のように、イベントが到達するクラスに読み取り専用のプライベート フィールドを実装します。

Private ReadOnly MyEventToken As SubscriptionToken =
Application.AppEventAggregator.GetEvent(Of MyEvent).Subscribe(Sub(eventMessage) DoSomethingWithTheString(EventMessage))

...DoSomethingWithTheString(eventMessage As String)イベントを処理する場所はどこになりますか。

もちろん、Prismには他にも(たくさん)ありますが、必要以上に使う必要はありません。また、他の人が指摘しているように、同じ問題を解決するための同様のアプローチを持つ他の多くのMVVMフレームワークがあります。

于 2013-08-06T21:17:35.670 に答える
2

メディエーターは正しい方向への一歩ですが、イベント アグリゲーターははるかに柔軟です。数十の実装を見つけることができます。たとえば、Prism にはすぐに使用できる実装があります。

通信は ViewModel 間で行われます。ViewModel は、アグリゲーターでの通知のために自身を登録し、アグリゲーターで通知を発生させます。

于 2013-08-06T20:02:55.350 に答える