0

1つ以上のサービスと通信する単純なネットワークアプリケーションを作成しているので、いくつかのキュー(送信メッセージと受信メッセージ用)、テーブル、アクティブな各接続のステータスを含むリストなどを使用することを計画しました。つまり、これらはアプリケーション自体の機能を保証するために必要なデータ構造です。

このアプリケーションには、アプリケーション自体の内部機能の一部を示すグラフィカルインターフェイスも装備されている必要があります。たとえば、キュ​​ーの充填ステータス、接続のステータス(検出された速度など)などです。 Model-View-ViewModelパターンの場合、モデルはGUIに表示されるデータで構成されます。このアプリケーションでは、前述のデータ構造がモデルを表します。つまり、モデルはアプリケーションのビジネスロジックを実装します。

ViewModelは、変更が発生したことをViewINotifyPropertyChangedに通知するためにインターフェイスを実装する必要がありますが、ModelはどのようにViewModelと通信しますか?この記事を読んだ後、インターフェイスがモデルによって実装されていることに気付きました。この答えはもう少し説明しますが、それは私を少し混乱させます:INotifyPropertyChanged

INotifyPropertyChanged-ViewModelとModelに入る必要があります(必要な場合)

なぜ、必要に応じて?このインターフェースはいつ実装する必要がありますか?いつ実装すべきではありませんか?

さらに、はインターフェイスDictionaryを実装していませんINotifyPropertyChanged。使用する場合、このインターフェイスを実装するクラスでラップする必要がありますか?

最後に、モデルは読み取り専用である必要があります。つまり、ユーザーはGUIを使用して内部データ構造の内容を変更することはできません。これを達成する方法は?

4

3 に答える 3

2

how does the Model to communicate with the ViewModel

好きなように。私たちが作成するほとんどのアプリでは、ビュー モデルがビジネス ロジック レイヤー (モデル) を呼び出します。ただし、ビュー モデルがモデルへの変更をすぐに (イベントで) 通知される必要がある場合は、モデルに INotifyPropertyChanged を実装できます。または、単にビュー モデルをモデルのイベントにサブスクライブさせることもできます。

Moreover, the Dictionary does not implement the INotifyPropertyChanged interface: if I use it, should I wrap it with a class which implements this interface?

ビュー モデルに INotifyPropertyChanged を実装するだけで済みます。ビュー モデル (ディクショナリ) 内のプロパティは、単に NotifyPropertyChanged (または実装のように見えるもの) を呼び出すだけです。

Finally, the model should be read-only, meaning that the user does not be able to change the contents of internal data structures using the GUI. How to accomplish this?

ユーザーがデータを変更できる機能をユーザーに提供しないでください。バインディングを一方向にするか、単に変更を行うための API を提供しないでください。

于 2012-08-16T23:48:11.050 に答える
1
  1. INotifyPropertyChanged は、主に ViewModel クラスによって実装されます。これは、ViewModel プロパティにバインドされているビュー内の UI コントロールが、プロパティが変更されたときに更新されるように、データ バインディングを容易にするためです。
    MVVM 設計パターンでは、関係は非常に単純で、一方向です。ビューはそれがViewModelであることを認識しており、ViewModelはモデルについて認識しています。モデルが更新された場合、更新を反映してビューに反映できるように、ViewModel は何らかの方法でそれを認識する必要があります。1 つの方法は、Model にも INotifyPropertyChanged を実装させ、ViewModel に対応するイベント ハンドラーを実装させることです。すべての変更が UI から駆動され、モデルにプッシュ バックされる場合、これはおそらく必要ありません。

  2. Dictionary に実際にバインドすることはできません。ObservableCollection を使用すると、それがうまくいく場合に理想的です。または、次の行に沿って Observable Dictionary を実装することを検討できます: http://drwpf.com/blog/2007/09/16/can-i-bind-my-itemscontrol-to-a-dictionary/

  3. MVVM はモデルをビューから分離しているため、ビューからモデルへの直接的な関係はありません。ViewModel の実装は、何かが Model に書き戻されるかどうかを制御します。

于 2012-08-16T23:41:36.987 に答える
0

INotifyPropertyChanged(INPC)は、モデルがViewModelでもない(つまり、「モデル」がない)場合を除いて、モデルに含めることはできません。INPCはビューモデルにのみ存在する必要があります。

モデルはビューモデルについて何も知らないはずなので、モデルと通信することはできません。ビューモデルのみがモデルと通信できます。

UIの観点からは、ビューモデルのみがデータを処理します。したがって、モデルを「読み取り専用」にする場合は、ビューモデルに実装しないでください。

バインドはビューモデルを使用して行われます。この場合、ディクショナリを使用しないでください(バインドするためにディクショナリをラップするコードを記述したい場合を除く)。ディクショナリがモデルにある場合は、ビューモデルでそれを「ラップ」する必要があります。コレクションの周りに監視可能なラッパーを作成するのは非常に簡単です。おそらく、ビューモデルはキーと値のペアを処理しません。UIが処理できる(そしてバインドできる)フラットなものを処理する必要があります。

更新
データバインディング用にINPCが導入されました。ビューを特定の具象クラスから分離するため、INPCについてのみ知る必要があります(分離の方向に注意してください)。MVVMの場合、これはビューをビューモデルから切り離します。PMの場合、これはビューをプレゼンターから切り離す可能性があります。MVCの場合、これはビューをコントローラーから切り離す可能性があります。MVPの場合、これはプレゼンターからの眺め。

データバインディングは、データをUI要素にバインドする手法です。データソースターゲットにバインドして、ターゲットが適切と思われる方法でデータを要求したり、ソースが適切と思われる方法でデータをプッシュしたりできるようにします(バインドのタイプに応じて、一方向または静的である可能性があり、方法が制限されます)多くの場合、get / pushが発生する可能性があります)。

データソースとターゲットの間の分離された関係の必要な性質により、データバインディングはUIの問題ではなく、データバインディングはどこにでも適用できると人々が信じる場合があります。つまり、データバインディングの実装はUIから完全に切り離されています。これは一般的に間違いです。データバインディングは、ビューを特定のクラスの特定の知識から切り離します(これは基本的な階層化とサイクルの回避であり、ここでは説明しません)。ただし、ビューをデータソースから完全に分離するわけではありません。バインディングはデータソースなしでは発生しません-そこにはまだある程度のカップリングがあり、緩和されたのはコンパイル時のカップリングだけです(テスト、柔軟性、堅牢性などの支援ですが、本番環境では実行時に存在する必要があります。つまり、INPC実装を実行時にUI要素にバインドせずにテストできるという事実は、UIフレームワークに依存していないことを意味するわけではありません。ビューがまだデータソースに緩く結合されているという事実は、この関係の唯一の結合ではありません。データソースは、UIフレームワークを介してビューに緩く結合されています(緩くはないにしても)。

すべてのUIフレームワークには、UI要素へのアクセスと変更をメインスレッドまたはUIスレッドで実行する必要があるという制限があります。(少なくともWindowsでは、他のプラットフォームで発生する可能性があります。私は他のプラットフォームに精通していません)。データバインディングを使用すると、ソースは間接的にコントロールにバインドされ、データの変更によって1つ以上のUI要素が直接変更されます(フレームワークに応じて、仲介者を使用できます。WinRTの値コンバーターと同様ですが、データの変換または変換を担当します)。つまり、データソースは、UIにバインドされていること、およびバインドされているUIフレームワークのタイプについての深い知識を持っている必要があります。UIフレームワークへのこの緊密な結合は、データソースを(まだ緩く)UIに明確に結合します。

これは、INPCの特定の実装が実際に1つだけのUIフレームワークにバインドされていることを意味します。そのオブジェクトはもはやどこでも使用できません(明らかにどこでも理想的であり、すべてのシナリオで何かを機能させることは不可能なことがよくあります。ここでのポイントは、1つまたは2つ以上のシナリオでの高い凝集度です)。たとえば、INPCの実装がマルチスレッド環境で使用されている場合、プロパティ通知を送信する前に、データをUIスレッドに「マーシャリング」する必要があります。WinFormsでは、それControl.BeginInvokeは、WPFとSilverlightでは経由System.Windows.Threading.Dispatcherです。WinRTでは、それは経由Windows.UI.CoreDispatcherです。すべての場合において、INPC実装は1つのUIフレームワークに直接結合する必要があります。Silverlightの場合、これは「デスクトップ」のいずれかに直接結合します。DispatcherまたはWindowsPhone Dispatcher

品質メトリックには、凝集性などの概念が含まれます。凝集度は、2つのコード単位がどれほど強く関連しているかを示す尺度です。UI以外で使用されるINPCの実装は、その1つの特定のUIフレームワークをサポートするために必要なすべてのインフラストラクチャの性質により、UIの外部で使用できる可能性はありますが、すべてのUIフレームワークに関連するコードは使用されません。つまり、UIから完全に切り離すには、あまりにも多くの責任を負います。はい、どこでもINPCを実装するオブジェクトを使用でき、PropertyChangedイベントを使用することはできませんが、その場合、結合率は低くなります(悪いと見なされます)。

モデルにINPCを実装し、そのモデルをUIとWCFまたはWebサービスのバックエンドの両方で使用したい場合は、使用できないか、バックエンドがUIフレームワークを参照する必要があります。そのモデルを別のタイプのUIで使用したい場合、そのINPCの実装は特定のUIフレームワークに依存しているため、使用できませんでした。別の「モデル」を作成する必要があります。その時点で、それは明らかに「ビューモデル」です。

INPC自体は特定のUIフレームワークにバインドされていません(バインドされるべきではありません)。これは、INPCがどこでも使用できるという誤解につながります。 はい、高レベルの名前空間への結合がないということは、それが可能であることを意味しますが、INPCの圧倒的な使用法は、ターゲットがUIの場合です。真の「バインディング」としてUIを含まないINPCの他の使用法に挑戦したいと思います。他のツールと同様に、それを誤用して有用な結果を得ることができます。INPCは、データの投影、データの変換などに使用できますしかし、これらはINPCの誤用であり、この質問の焦点から外れていると思います...

于 2012-08-17T00:35:53.993 に答える