3

私のアプリケーションには、単一のサービス (リポジトリ、DAO など) を持つ複数の ViewModel があります。これをWidgetServiceと呼び、それらに注入します。

これらの ViewModel の 1 つが、すべてのユーザー ウィジェットのリストであるとしましょう。もう 1 つは、これらのウィジェットの 1 つを編集/作成するための ViewModel です。

ユーザーは、WidgetListViewModel に基づく WidgetListView でウィジェットのリストを表示しボタンクリックして新しいウィジェットを追加できます。この新しいウィジェットを作成するために、CreateWidgetViewModelが新しく作成され、一部の UserControl/Window の DataContext に挿入されます。したがって、CreateWidgetViewCreateWidgetViewModelを表示する DataTemplates の魔法を使用します。また、CreateWidgetViewModelの新規作成は、必ずしもWidgetListViewModelのスコープ内で行われるとは限りません。

WidgetListViewModelの場合、WidgetServiceのインスタンスが注入されました。CreateWidgetViewModelには、この同じWidgetServiceインスタンスが挿入されました。

ここで、ユーザーがCreateWidgetViewで保存をクリックすると、 WidgetServiceSaveメソッドが呼び出され、ウィジェットが永続化されます。ここで、WidgetListViewModelに、表示する新しいウィジェットがあることを通知する必要があります。

長いビルドアップは、次の質問につながります:新しいウィジェットを表示する必要があることをWidgetListViewModelに知らせるにはどうすればよいですか?

Microsoft の担当者が、ViewModel がサブスクライブしているサービスのイベントを使用して、この種のことを行っているビデオを見たことがあります。ただし、これの欠点は、サービスがビューモデルよりも長く存続する場合、サービスがGCされるまでビューモデルがGCされないことです。ViewModel に IDisposable を追加できます。しかし、ViewModel が DataTemplates を介して UI でのみ表現されている場合、いつ/どのように Dispose を呼び出すのでしょうか?

これに関する提案はありますか?

明確にするために、MVVM の私の解釈は Josh Smith の解釈に最もよく似ていると言えます。少なくとも、私の MVVM アーキテクチャは Crack.Net ソースにあるものとほぼ一致しています。

4

5 に答える 5

1

Prism(http://www.codeplex.com/CompositeWPF)のEventAggregatorを使用します。これは、publisher-subscriberパターンを使用して、ターゲット要素とソース要素の間の結合を失います。説明するシナリオにぴったりです。

于 2009-03-14T20:01:56.660 に答える
1

わかりました、これに対する答えがまだないので、試してみようと思いましたが、私は MVVM の専門家ではありません。

イベントはこれで行く方法のようです。ただし、ご指摘のとおり、サービスが ViewModel よりも長く存続すると、メモリ リークが発生する可能性があります。これに対処する最善の方法は、弱いイベント リスナーを使用することです。

弱いイベントを使用すると、弱い参照を使用してイベントに接続できるため、ソース オブジェクトが GC されている場合、イベント ハンドラーによってソースが保持されません。

于 2009-03-14T12:03:55.357 に答える
0

いくつかのオプションがあります:

  1. ObservableCollectionを使用する-これはおそらく最も簡単なオプションですが、モデルに何らかの「マスター」コレクションがあり、UIをこのコレクションに直接バインドする必要があります。これは「クリーンな」MVVMアーキテクチャではない可能性がありますが、おそらく最も簡単な方法です。仕事を成し遂げるために。

  2. イベントを使用し、MVVMで行うのは簡単ではなく、自分の後でクリーンアップするようにしてください。

  3. 仲介者を使用してイベントを自動的にクリーンアップします(他の人が提案したように)が、独自に作成しないでください。これには多くの落とし穴があります。WPFにはそれを行う組み込みのクラスがありますが、名前を忘れました(誰かが覚えている場合)名前コメントを残してください)。

  4. 定期的に更新を行い、ViewModelクラスでX秒ごとにリストを更新します。これは、管理する必要のある何らかの通知メカニズムなしで更新を取得する唯一の方法です。

于 2009-03-15T10:07:55.657 に答える
0

この同じ問題を解決するために、オブザーバーパターン(別名パブリッシュ/サブスクライブパターン)を使用しました。すべての共有メソッドとデータメンバーを持つEventAggregatorというクラスを作成しました。WidgetListViewModelでイベントに登録し、CreateWidgetViewModelで「WidgetCreated」イベントを公開できます。WidgetListViewModelにIDisposable(より良い)を実装させてイベントの登録を解除するか、Finalizeメソッドで登録を解除することができます。それはかなりうまくいきました、そして最も良い部分は、2つのビューモデルがお互いについて何の考えも持っている必要がなかったということです。

より複雑な場合、またはサービスとアプリのバージョンの違いをサポートする必要がある場合は、この種の処理を行うModelViewを実装して、アプリケーションのパターンをM-MV-VM-Vにすることができます。少しやり過ぎに見えるかもしれませんが、特定のクラスの問題を維持するのがはるかに簡単になる可能性があります。VMとUNDOコード間のクロストークがばかげているので、MVを挿入したかったプロジェクトがいくつかあったことは知っています。

于 2009-03-14T19:50:11.943 に答える
0

Cameron が WeakEvent パターンを使用することに同意します。WeakEvent パターンをサポートする ViewModel の基本クラスを作成しました (この例では、PresentationModel という名前を使用しています)。

私のサンプル プロジェクトが役に立つかもしれません: http://www.codeplex.com/CompositeExtensions

jbe

于 2009-03-24T13:09:36.660 に答える