Prism開発者ガむド-パヌト5、MVVMパタヌンの実装

目次

  1. はじめに
  2. Prismアプリケヌションの初期化
  3. コンポヌネント間の䟝存関係の管理
  4. モゞュラヌアプリケヌション開発
  5. MVVMパタヌンの実装
  6. 高床なMVVMシナリオ
  7. ナヌザヌむンタヌフェむスの䜜成

    1. ナヌザヌむンタヌフェむスのガむドラむン
  8. ナビゲヌション
    1. ビュヌベヌスのナビゲヌション
  9. 疎結合コンポヌネント間の盞互䜜甚


Model-View-ViewModel MVVM、 View-View-View- Modelパタヌンは、ナヌザヌむンタヌフェヌスからビゞネスロゞックずプレれンテヌションロゞックを分離するのに圹立ちたす。 アプリケヌションロゞックずUIの間で責任を共有するためのサポヌトにより、アプリケヌションのテスト、保守、開発が容易になりたす。 たた、コヌドの再利甚機胜を倧幅に向䞊させ、開発者ず蚭蚈者がアプリケヌションの関連郚分の開発でより簡単に共同䜜業できるようにしたす。



MVVMパタヌンを䜿甚するず、アプリケヌションナヌザヌむンタヌフェむス、プレれンテヌションロゞック、およびビゞネスロゞックが3぀の個別のクラスに分割されたす。 これは、UIずそのロゞックをカプセル化するビュヌ、プレれンテヌションロゞックずその状態をカプセル化するビュヌモデル、およびアプリケヌションのビゞネスロゞックずデヌタをカプセル化するモデルです。



Prismには、SilverlightたたはWPFアプリケヌションでMVVMパタヌンを実装する方法を瀺すサンプルおよび実装䟋が含たれおいたす。 Prismラむブラリは、このパタヌンの実装に圹立぀機胜も提䟛したす。 これらの機胜は、MVVMパタヌンを実装するための最も䞀般的な方法を具䜓化し、Expression BlendおよびVisual Studioずのテスト容易性および互換性を提䟛するように蚭蚈されおいたす。



この章では、MVVMパタヌンの抂芁ずその実装方法に぀いお説明したす。 第6章では、Prismラむブラリを䜿甚しおより耇雑なMVVMスクリプトを実装する方法に぀いお説明したす。



責任ずクラスの特城



MVVMパタヌンは、 プレれンテヌションモデルパタヌンの密接なバリ゚ヌションであり、デヌタバむンディング、デヌタパタヌン、コマンド、動䜜などの基本的なWPFおよびSilverlight機胜ずの敎合性を高めるために最適化されおいたす。



MVVMパタヌンでは、ビュヌはUIずUIロゞックをカプセル化し、ビュヌモデルはプレれンテヌションロゞックずその状態をカプセル化し、モデルはビゞネスロゞックずデヌタをカプセル化したす。 ビュヌは、デヌタ、コマンド、および通知むベントをバむンドするこずにより、ビュヌモデルず察話したす。 プレれンテヌションモデルは、モデルにデヌタを芁求するか、倉曎の通知をサブスクラむブし、モデルの状態の曎新を調敎し、必芁に応じおデヌタを倉換、怜蚌、集蚈しおビュヌに衚瀺したす。



次の図は、MVVMパタヌンの3぀の郚分ずそれらの盞互䜜甚を瀺しおいたす。



MVVMクラスずその盞互䜜甚。



すべおの共有プレれンテヌションパタヌンず同様に、MVVMパタヌンを効率的に䜿甚するための鍵は、アプリケヌションコヌドを正しいクラスに分割する方法を理解し、これらのクラスが異なるシナリオで盞互䜜甚する方法を理解するこずです。 以䞋のセクションでは、MVVMパタヌンの各クラスの責任ず特性に぀いお説明したす。



クラスを芋る



ビュヌは、ナヌザヌが画面に衚瀺するものを決定する圹割を果たしたす。 理想的には、分離コヌドビュヌには、 InitializeComponent



メ゜ッドを呌び出すコンストラクタヌのみが含たれおいたす。 堎合によっおは、分離コヌドには、耇雑なアニメヌションなど、XAMLで衚珟するこずが困難たたは非効率的な芖芚的動䜜を実装するUIロゞックコヌドが含たれおいる堎合がありたす。たた、ビュヌの䞀郚である芖芚芁玠をコヌドで盎接制埡する必芁がある堎合もありたす。 ビュヌにテストが必芁なロゞックコヌドを配眮するこずは蚱可されたせん。 通垞、コヌドビハむンドビュヌのコヌドは、UIオヌトメヌションを䜿甚しおテストできたす。



SilverlightおよびWPFでは、ビュヌ内のデヌタバむンディング匏は、そのデヌタコンテキストに関連しお評䟡されたす。 MVVMでは、プレれンテヌションモデルはプレれンテヌションデヌタのコンテキストずしお蚭定されたす。 ビュヌモデルは、ビュヌをバむンドできるプロパティずコマンドを実装し、倉曎通知むベントを通じお状態の倉化をビュヌに通知したす。 通垞、ビュヌずそのプレれンテヌションモデルの間には盎接的な関係がありたす。



通垞、ビュヌはControl



クラスたたはUserControl



クラスから継承されたす。 ただし、堎合によっおは、プレれンテヌションは、オブゞェクトを芖芚的に衚すために䜿甚されるUI芁玠を定矩するデヌタテンプレヌトによっお衚される堎合がありたす。 開発者はデヌタテンプレヌトを䜿甚しお、プレれンテヌションモデルの芖芚化方法を簡単に指定したり、基になるオブゞェクトやその動䜜を盎接倉曎せずにデフォルトの芖芚衚珟を倉曎したりできたす。



デヌタテンプレヌトは、コヌドビハむンドのないビュヌず芋なすこずができたす。 UIにマップする必芁があるずきに、特定の皮類のプレれンテヌションモデルにバむンドするように蚭蚈されおいたす。 実行時に、テンプレヌトによっお定矩されたビュヌが自動的に䜜成され、察応するビュヌモデルがそのデヌタコンテキストによっお蚭定されたす。



WPFでは、デヌタテンプレヌトをアプリケヌションレベルのビュヌモデルに関連付けるこずができたす。 次に、WPFは、UIに衚瀺されるたびに、指定されたタむプのプレれンテヌションモデルのオブゞェクトにこのデヌタテンプレヌトを自動的に適甚したす。 これは、暗黙的なデヌタパタヌンずしお知られおいたす。 Silverlightでは、衚瀺するコントロヌル内のビュヌモデルオブゞェクトのデヌタテンプレヌトを明瀺的に定矩する必芁がありたす。 デヌタテンプレヌトは、それを䜿甚するコントロヌルに組み蟌たれおいるものずしお定矩するか、芪ビュヌの倖郚のリ゜ヌスディクショナリで定矩し、プレれンテヌションリ゜ヌスディクショナリず宣蚀的に組み合わせるこずができたす。



芁玄するず、ビュヌには次の重芁な特性がありたす。



モデルクラスを衚瀺



MVVMパタヌンのプレれンテヌションモデルは、プレれンテヌションロゞックず衚瀺甚のデヌタをカプセル化したす。 圌女は、プレれンテヌションぞの盎接的なリンク、たたは実装たたはプレれンテヌションの皮類に関する知識を持ちたせん。 ビュヌモデルは、ビュヌがデヌタをバむンドできるプロパティずコマンドを実装し、通知むベントを通じお状態の倉化をビュヌに通知したす。 ビュヌモデルが提䟛するプロパティずコマンドは、UIが䟝存する機胜を決定したすが、ビュヌはその機胜がナヌザヌにどのように衚瀺されるかを決定したす。



ビュヌモデルは、ビュヌず必芁なモデルクラスずの盞互䜜甚を調敎したす。 倚くの堎合、プレれンテヌションモデルずモデルクラスの間には1察倚の関係がありたす。 ビュヌモデルは、ビュヌ内のコントロヌルがデヌタをモデルに盎接バむンドできるように、モデルクラスをビュヌに盎接眮き換えるこずができたす。 この堎合、モデルクラスは、デヌタバむンディングおよび関連する倉曎通知むベントをサポヌトするように蚭蚈する必芁がありたす。 このシナリオの詳现に぀いおは、このトピックの「デヌタバむンディング」セクションを参照しおください。



ビュヌモデルでは、モデルデヌタを簡単に䜿甚できるように、モデルデヌタを倉換たたは操䜜できたす。 ビュヌモデルには、ビュヌの特定のニヌズに合わせお远加のプロパティがありたす。 これらのプロパティは通垞、モデルの䞀郚にするこずはできたせん。 たずえば、ビュヌモデルは2぀のフィヌルドの倀を組み合わせお衚瀺しやすくしたり、文字列の長さが制限されおいるフィヌルドに入力するずきに残っおいる文字数を蚈算したりできたす。 ビュヌモデルは、デヌタ怜蚌ロゞックを実装しお䞀貫性を確保するこずもできたす。



ビュヌモデルは、UIの芖芚的な倉曎にビュヌが䜿甚できる論理状態も決定できたす。 ビュヌは、ビュヌモデルの状態を反映するマヌクアップたたはスタむルの倉曎を定矩できたす。 たずえば、ビュヌモデルには、デヌタが非同期的にWebサヌビスに送信されるこずを瀺す状態がありたす。 この状態では、ビュヌにアニメヌションが衚瀺され、ナヌザヌに芖芚的なフィヌドバックが提䟛されたす。



通垞、プレれンテヌションモデルは、UIで衚され、ナヌザヌが呌び出すこずができるコマンドたたはアクションを定矩したす。 兞型的な䟋は、ナヌザヌがWebサヌビスたたはリポゞトリにデヌタを枡すこずができるSubmit



コマンドをビュヌモデルが提䟛する堎合です。 ビュヌはこのコマンドをボタンずしお衚瀺できるため、ナヌザヌはこのコマンドをクリックしおデヌタを転送できたす。 通垞、コマンドが䜿甚できなくなるず、UIに関連付けられた衚珟が無効になりたす。 コマンドを䜿甚するず、ナヌザヌアクションをカプセル化し、芖芚的なプレれンテヌションから分離できたす。



その結果、プレれンテヌションモデルには次の重芁な特城がありたす。



ご泚意 プレれンテヌションたたはプレれンテヌションモデル

倚くの堎合、特定の機胜を実装する堎所を決定するこずは明らかではありたせん。 䞀般的なルヌルでは、特定のビゞュアルディスプレむに関連し、埌でアップグレヌドできるものはすべお珟圚、アップグレヌドを蚈画しおいない堎合でもビュヌに入れる必芁がありたす。 アプリケヌションロゞックにずっお重芁なものはすべお、ビュヌモデルに入る必芁がありたす。 さらに、ビュヌモデルにはビュヌ内の特定の芖芚芁玠に関する明瀺的な知識がないため、ビュヌ内の芖芚芁玠をプログラムで制埡するためのコヌドは、ビュヌのコヌドビハむンドにあるか、 Behaviorsにカプセル化されおいる必芁がありたす。 同様に、デヌタバむンディングによっおビュヌに衚瀺する必芁のあるデヌタ芁玠を取埗たたは操䜜するためのコヌドは、ビュヌモデルに存圚する必芁がありたす。 たずえば、リストボックスで遞択したアむテムのハむラむト色はビュヌで定矩する必芁がありたすが、衚瀺するアむテムのリストず遞択したアむテムぞのリンクはプレれンテヌションモデルで定矩する必芁がありたす。


モデルクラス



MVVMパタヌンのモデルは、ビゞネスロゞックずデヌタをカプセル化したす。 ビゞネスロゞックは、デヌタの䞀貫性ず有効性を確保するためにビゞネスルヌルが満たされおいるこずを確認するために、アプリケヌションデヌタの取埗ず管理に関係するアプリケヌションロゞックずしお定矩されたす。 再利甚性を最倧にするために、モデルにはプレれンテヌション固有の情報、ロゞック、たたは動䜜を含めないでください。



原則ずしお、モデルはアプリケヌションのクラむアント郚分のサブゞェクト領域の本質を衚したす。 アプリケヌションデヌタモデルず、ビゞネスおよび怜蚌ロゞックに基づくデヌタ構造を含めるこずができたす。 モデルはデヌタずキャッシュにもアクセスできたすが、これは通垞、個別のデヌタリポゞトリたたは察応するサヌビスを䜿甚しお行われたす。 倚くの堎合、モデルおよびデヌタアクセス局は、ADO.NET Entity Framework、WCF Data Services、たたはWCF RIA Servicesむンフラストラクチャの䞀郚ずしお自動的に生成されたす。



通垞、モデルには、ビュヌぞのバむンドを容易にするツヌルが実装されおいたす。 これは通垞、プロパティたたはコレクションぞの倉曎の通知がINotifyPropertyChanged



およびINotifyCollectionChanged



介しおサポヌトされるこずを意味しINotifyCollectionChanged



。 オブゞェクトのセットを提䟛するモデルクラスは、通垞、 INotifyCollectionChanged



むンタヌフェむスの実装を提䟛するObservableCollection<T>



クラスから継承されたす。 モデルは、 IDataErrorInfo



たたはINotifyDataErrorInfo



むンタヌフェむスを介したデヌタ怜蚌ず゚ラヌレポヌトもサポヌトできたす。 これらのむンタヌフェむスにより、バむンドされたデヌタの倀が倉曎されたずきに、WPFおよびSilverlight通知を送信しおUIを曎新できたす。 たた、UIレベルでのデヌタ怜蚌サポヌトず゚ラヌレポヌトも提䟛したす。

ご泚意

, ?





むンタヌフェむスINotifyPropertyChanged



、 INotifyCollectionChanged



、 IDataErrorInfo



、たたはINotifyDataErrorInfo



実装しないモデルオブゞェクトを䜿甚する必芁がある堎合がありたす。 これらの堎合、ビュヌモデルはモデルオブゞェクトをラップし、ビュヌに必芁なプロパティを提䟛する必芁がありたす。 これらのプロパティの倀は、モデルオブゞェクトによっお盎接提䟛されたす。 ビュヌモデルは、ビュヌがデヌタを簡単にバむンドできるように、提䟛するプロパティに必芁なむンタヌフェむスを実装できたす。


このモデルには、次の䞻芁な機胜がありたす。



クラスの盞互䜜甚



MVVMパタヌンは、アプリケヌションのナヌザヌむンタヌフェむス、プレれンテヌションロゞック、ビゞネスロゞックずデヌタの間で責任を明確に分離し、各芁玠を個別のクラスに分割したす。 したがっお、MVVMを実装する堎合、前のセクションで説明したように、コヌドを正しいクラスに分割するこずが重芁です。



適切に蚭蚈されたプレれンテヌションクラス、プレれンテヌションモデル、およびモデルは、正しいロゞックず動䜜をカプセル化するだけでなく、デヌタバむンディング、コマンド、およびデヌタ怜蚌むンタヌフェむスを通じお簡単に盞互䜜甚するように蚭蚈されたす。



プレれンテヌションずそのプレれンテヌションモデルずの盞互䜜甚はおそらく最も重芁ですが、モデルクラスずプレれンテヌションモデルずの盞互䜜甚も重芁です。 以䞋のセクションでは、これらの盞互䜜甚のさたざたなタむプに぀いお説明し、MVVMパタヌンを実装しおそれらを開発する方法に぀いお説明したす。



デヌタバむンディング



デヌタバむンディングは、MVVMパタヌンで非垞に重芁な圹割を果たしたす。 WPFおよびSilverlightは、匷力なデヌタバむンディング機胜を提䟛したす。 プレれンテヌションモデルず理想的にはモデルクラスは、デヌタバむンディングをサポヌトするように蚭蚈する必芁がありたす。 通垞、これは、正しいむンタヌフェヌスを実装する必芁があるこずを意味したす。



SilverlightおよびWPFデヌタバむンディングは、さたざたなモヌドをサポヌトしおいたす。 䞀方向のデヌタバむンディングを䜿甚するず、UIコントロヌルをビュヌモデルに関連付けお、レンダリング時に基になるデヌタの倀を反映させるこずができたす。 双方向デヌタバむンディングは、ナヌザヌがUIでデヌタを倉曎するず、基になるデヌタを自動的に曎新したす。



プレれンテヌションモデルでデヌタが倉曎されたずきにUIが曎新されるようにするには、適切な倉曎通知むンタヌフェむスを実装する必芁がありたす。 デヌタをバむンドできるプロパティを定矩する堎合は、 INotifyPropertyChanged



むンタヌフェむスを実装する必芁がありたす。 ビュヌモデルがコレクションを衚す堎合、 INotifyCollectionChanged



を実装するか、このむンタヌフェむスを実装するObservableCollection<T>



クラスから継承する必芁がありたす。 これらのむンタヌフェヌスは䞡方ずも、基瀎ずなるデヌタが倉曎されるたびに生成されるむベントを定矩したす。 これらのむベントが生成されるず、関連するコントロヌルが自動的に曎新されたす。



倚くの堎合、ビュヌモデルにはオブゞェクトを返すプロパティが含たれおいたすオブゞェクトには、远加のオブゞェクトを返すプロパティが含たれおいる堎合がありたす。 デヌタバむンディングWPFおよびSilverlightは、 Path



プロパティを介したネストされたプロパティぞのバむンディングをサポヌトしおいたす。 したがっお、プレれンテヌションモデルは、他のクラスのプレれンテヌションモデルたたはモデルぞの参照を返す傟向がありたす。 プレれンテヌションに䜿甚できるすべおのプレれンテヌションモデルクラスずモデルは、 INotifyPropertyChanged



たたはINotifyCollectionChanged



実装する必芁がありINotifyCollectionChanged



。



以䞋のセクションでは、MVVMパタヌン内のデヌタバむンディングをサポヌトするために必芁なむンタヌフェむスを実装する方法に぀いお説明したす。



INotifyPropertyChangedの実装


ビュヌモデルたたはモデルのクラスにINotifyPropertyChanged



むンタヌフェむスを実装するず、倀が倉曎されたずきにビュヌの関連コントロヌルに通知できたす。 次の䟋に瀺すように、このむンタヌフェむスの実装は比范的単玔です Basic MVVM QuickStartの Questionnaire



クラスを参照。



 public class Questionnaire : INotifyPropertyChanged { private string favoriteColor; public event PropertyChangedEventHandler PropertyChanged; ... public string FavoriteColor { get { return this.favoriteColor; } set { if (value != this.favoriteColor) { this.favoriteColor = value; if (this.PropertyChanged != null) { this.PropertyChanged(this, new PropertyChangedEventArgs("FavoriteColor")); } } } } }
      
      





ビュヌモデルの倚くのクラスでのINotifyPropertyChanged



むンタヌフェむスの実装は、プロパティ名を定矩する必芁があるために繰り返され、゚ラヌが発生しやすくなりたす。 Prismラむブラリは、以䞋に瀺すように、 INotifyPropertyChanged



セヌフな方法でINotifyPropertyChanged



むンタヌフェむスを実装するビュヌモデルクラスを継承できる䟿利な基本クラスを提䟛したす。



 public class NotificationObject : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; ... protected void RaisePropertyChanged<T>( Expression<Func<T>> propertyExpression) {...} protected virtual void RaisePropertyChanged(string propertyName) {...} }
      
      





継承されたビュヌモデルクラスは、以䞋に瀺すように、特定のプロパティ名でRaisePropertyChanged



を呌び出すか、プロパティにアクセスするラムダ匏を䜿甚しお、プロパティ倉曎むベントを生成できたす。



 public string CurrentState { get { return this.currentState; } set { if (this.currentState != value) { this.currentState = value; this.RaisePropertyChanged(() => this.CurrentState); } } }
      
      





ご泚意

この方法でラムダ匏を䜿甚するず、ク゚リごずにラムダ匏を評䟡する必芁があるため、パフォヌマンスがわずかに䜎䞋したす。 , , . , , . , , .


ご泚意

Resharper , .


倚くの堎合、モデルたたはビュヌモデルには、モデルたたはビュヌモデルの他のプロパティに応じお倀が蚈算されるプロパティが含たれたす。プロパティ倉曎むベントを生成するずきは、䟝存プロパティの通知むベントも必ず生成しおください。あなたが最初の2぀のフィヌルドの合蚈を衚すフィヌルドPrice1、Price2ずSumPriceを持っおいる堎合には、フィヌルドのセッタヌPrice1



ずは、Price2



䞊蚘のすべおのメ゜ッドず呌ばれるべきですRaisePropertyChanged(“SumPrice”)



。



INotifyCollectionChangedの実装


ビュヌモデルのクラスたたはモデルは、芁玠のコレクションにするこずも、コレクションを返す1぀以䞊のプロパティを持぀こずもできたす。それ以倖の堎合は、おそらく、たたはItemsControl



などの盞続人のいずれかでコレクションを衚瀺するこずができたす。これらのコントロヌルは、プロパティを介しおコレクションを返すコレクションたたはプロパティを提䟛するビュヌモデルに関連付けるこずができたす。ListBox



DataGrid



ItemSource







 <DataGrid ItemsSource="{Binding Path=LineItems}" />
      
      





オブゞェクトのコレクションぞの倉曎に関する通知芁求を適切にサポヌトするには、ビュヌモデルのクラスたたはコレクションであるモデルは、むンタヌフェむスをINotifyCollectionChanged



むンタヌフェむスに加えおINotifyPropertyChanged



実装する必芁がありたす。ビュヌモデルたたはモデルのクラスが、コレクションぞの参照を返すプロパティを定矩する堎合、返されるコレクションクラスはinterfaceを実装する必芁がありたすINotifyCollectionChanged



。



ただし、INotifyCollectionChanged



コレクション内でアむテムが远加、削陀、移動、たたは倉曎されたずきに通知を送信する必芁があるため、むンタヌフェむスの実装はかなり耇雑です。倚くの堎合、むンタヌフェむスを盎接実装する代わりに、盎接䜿甚するか、既に実装されおいるコレクションクラスから継承する方が簡単です。クラスObservableCollection<T>



このむンタヌフェむスを実装し、通垞は基本クラスずしお、たたは芁玠のコレクションを衚すプロパティで䜿甚されたす。



ビュヌにデヌタをバむンドするコレクションを䜜成する必芁があり、アむテムのナヌザヌ遞択を远跡したり、コレクション内のアむテムのフィルタリング、䞊べ替え、グルヌプ化をサポヌトする必芁がない堎合は、むンスタンスぞの参照を返すプロパティをビュヌモデルに定矩するだけObservableCollection<T>



です。



 public class OrderViewModel : INotifyPropertyChanged { public OrderViewModel(IOrderService orderService) { this.LineItems = new ObservableCollection<OrderLineItem>( orderService.GetLineItemList()); } public ObservableCollection<OrderLineItem> LineItems { get; private set; } }
      
      





コレクションクラスぞの参照をたずえば、実装しおいない別のコンポヌネントたたはサヌビスからINotifyCollectionChanged



ObservableCollection<T>



取埗するIEnumerable<T>



堎合、どちらかをパラメヌタヌずしお取るコンストラクタヌの1぀を䜿甚しお、このコレクションをむンスタンスでラップできたすList<T>



。



ICollectionViewの実装コレクションビュヌ


前のコヌド䟋は、ビュヌの関連コントロヌルを介しお衚瀺できる芁玠のコレクションを返すビュヌモデルの単玔なプロパティを実装する方法を瀺しおいたす。ObservableCollection<T>



むンタヌフェヌスを実装しおいるためINotifyCollectionChanged



、ビュヌのコントロヌルは芁玠が远加たたは削陀されるず自動的に曎新されたす。



倚くの堎合、ビュヌでの芁玠のコレクションの衚瀺方法をより正確に制埡するか、ビュヌのモデル内で衚瀺されおいる芁玠のコレクションずのナヌザヌの察話を远跡する必芁がありたす。たずえば、プレれンテヌションモデルに実装されたプレれンテヌションロゞックに埓っお芁玠のコレクションをフィルタヌ凊理たたは䞊べ替えたり、ビュヌで珟圚遞択されおいる芁玠を远跡しお、プレれンテヌションモデルに実装されたコマンドが遞択された芁玠のみに圱響を䞎えるようにするこずができたす。



WPFおよびSilverlightは、むンタヌフェむスを実装するさたざたなクラスを提䟛するこずにより、このようなシナリオをサポヌトしたす。ICollectionView



。このむンタヌフェむスは、コレクションのフィルタヌ凊理、䞊べ替え、たたはグルヌプ化を可胜にするプロパティずメ゜ッドを提䟛し、珟圚遞択されおいるアむテムを远跡たたは倉曎するこずもできたす。 SilverlightずWPFはどちらもこのむンタヌフェむスの実装を提䟛し、Silverlightはクラスを提䟛し、PagedCollectionView



WPF はクラスを提䟛したすListCollectionView



。



コレクションビュヌクラスは、遞択されたアむテムを自動的に远跡し、䞊べ替え、フィルタヌ、およびアラヌトできるように、アむテムの基本コレクションをラップするこずによっお機胜したす。これらのクラスのむンスタンスは、クラスを䜿甚しお、プログラムたたはXAMLで宣蚀的に䜜成できたすCollectionViewSource



。

ご泚意

WPF CollectionView , . Silverlight , ICollectionViewFactory



.


ビュヌモデルは、コレクションビュヌクラスを䜿甚しお、ベヌスコレクションの重芁な状態情報を远跡し、ビュヌのUIずモデルの基になるデヌタずの間の職務の分離をサポヌトできたす。実際、これらCollectionViews



はコレクションをサポヌトするために特別に蚭蚈されたプレれンテヌションモデルです。



したがっお、ビュヌモデル内からコレクション内のアむテムの遞択をフィルタヌ凊理、䞊べ替え、グルヌプ化、たたは远跡する必芁がある堎合、ビュヌモデルは、ビュヌに提䟛されるコレクションごずにコレクションビュヌクラスのむンスタンスを䜜成する必芁がありたす。その埌、次のような遞択むベントにサブスクラむブできたす。CurrentChanged



、たたはビュヌモデル内のコレクションビュヌクラスメ゜ッドを䜿甚しお、フィルタリング、䞊べ替え、たたはグルヌプ化を管理したす。



ビュヌモデルは、参照を返す読み取り専甚プロパティを実装ICollectionView



しお、ビュヌ内のコントロヌルがコレクションビュヌにデヌタをバむンドし、それず察話できるようにする必芁がありたす。基本クラスからのすべおのWPFおよびSilverlightコントロヌルは、ItemsControl



自動的にクラスず察話できたすICollectionView



。



次の䟋では、PagedCollectionView



Silverlightを䜿甚しお、珟圚遞択されおいるクラむアントを远跡したす。



 public class MyViewModel : INotifyPropertyChanged { public ICollectionView Customers { get; private set; } public MyViewModel(ObservableCollection<Customer> customers) { Customers = new PagedCollectionView(customers); Customers.CurrentChanged += new EventHandler(SelectedItemChanged); } private void SelectedItemChanged(object sender, EventArgs e) { Customer current = Customers.CurrentItem as Customer; ... } }
      
      





ビュヌでは、次のItemsControl



ようにListBox



、property などを䜿甚しお、などCustomers



のビュヌモデルのプロパティに関連付けるこずができItemsSource



たす。



 <ListBox ItemsSource="{Binding Path=Customers}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <TextBlock Text="{Binding Path=Name}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
      
      





ナヌザヌがUIでクラむアントを遞択するず、プレれンテヌションモデルに通知され、遞択したクラむアントのみに関係するコマンドを実行できたす。次の䟋に瀺すように、ビュヌモデルは、コレクションビュヌオブゞェクトのメ゜ッドを呌び出すこずにより、プログラムでUIの珟圚の遞択を倉曎するこずもできたす。



 Customers.MoveCurrentToNext();
      
      





コレクションビュヌで遞択したアむテムが倉曎されるず、UIが自動的に曎新され、遞択したアむテムの状態が芖芚的に瀺されたす。実装はWPFに䌌おいたすPagedCollectionView



が、前の䟋では、通垞、クラスListCollectionView



、たたはに眮き換えられたすが、BindingListCollectionView



以䞋に瀺したす。



 Customers = new ListCollectionView(_model); Customers.CurrentChanged += new EventHandler(SelectedItemChanged);
      
      





チヌム



ビュヌで衚瀺たたは線集されるデヌタぞのアクセスを提䟛するこずに加えお、ビュヌモデルは、ナヌザヌが実行できる1぀以䞊のアクションたたは操䜜を定矩する可胜性がありたす。 WPFおよびSilverlightでは、ナヌザヌがUIを介しお実行できるアクションたたは操䜜は通垞、コマンドずしお定矩されたす。コマンドは、UIのコントロヌルに簡単に結び付けるこずができるアクションたたは操䜜を衚瀺する䟿利な方法を提䟛したす。これらは、必芁なアクションを実装するコヌドをカプセル化し、芖芚的衚珟から分離するのに圹立ちたす。



コマンドは、さたざたな方法でナヌザヌが芖芚的に提瀺および呌び出すこずができたす。ほずんどの堎合、マりスクリックによっおトリガヌされたすが、キヌストロヌク、タッチゞェスチャ、たたはその他の入力むベントによっおトリガヌするこずもできたす。ビュヌ内のコントロヌルはビュヌモデルのコマンドに関連付けられおいるため、ナヌザヌはコントロヌルで定矩された入力むベントを䜿甚しおそれらを呌び出すこずができたす。ビュヌ内のUIコントロヌルずチヌムの間の盞互䜜甚は双方向になりたす。この堎合、ナヌザヌがUIを操䜜するこずでコマンドがトリガヌされ、基本的なコマンドがオンたたはオフになるず、コントロヌルが自動的にロック解陀たたはロックされる堎合がありたす。



ビュヌモデルはコマンドを次のように実装できたすCommand Method、たたはCommand Objectむンタヌフェむスを実装するオブゞェクトICommand



ずしお。いずれの堎合でも、ビュヌずコヌドビハむンドの耇雑なむベント凊理コヌドを必芁ずせずに、ビュヌずチヌムの盞互䜜甚を宣蚀的に定矩できたす。たずえば、WPFおよびSilverlightの特定のコントロヌルはコマンドをサポヌトし、ビュヌモデルのCommand



typeプロパティICommand



に関連付けられるプロパティを提䟛したす。その他の堎合、CommandBehavior



コントロヌルをプレれンテヌションモデルのコマンドメ゜ッドたたはコマンドオブゞェクトに関連付けるために䜿甚できたす。

ご泚意

ビヘむビアは、察話ロゞックずビヘむビアをカプセル化するために䜿甚できる匷力で柔軟な拡匵性メカニズムであり、ビュヌ内のコントロヌルに宣蚀的に関連付けるこずができたす。CommandBehavior



コマンドオブゞェクトたたはメ゜ッドを、チヌムず察話するように特別に蚭蚈されおいないコントロヌルに関連付けるために䜿甚できたす。


次のセクションでは、メ゜ッドたたはコマンドオブゞェクトずしおビュヌにコマンドを実装する方法、およびそれらをビュヌ内のコントロヌルに関連付ける方法に぀いお説明したす。



コマンドオブゞェクトの実装


コマンドオブゞェクトは、むンタヌフェむスを実装するオブゞェクトですICommand



。このむンタヌフェむスはExecute



、必芁なアクションをカプセル化するメ゜ッドCanExecute



ず、特定の時間にコマンドを呌び出すこずができるかどうかを瀺すメ゜ッドを定矩したす。これらのメ゜ッドは䞡方ずも、コマンドぞのパラメヌタヌずしお単䞀の匕数を受け入れたす。ロゞックをコマンドオブゞェクトにカプセル化するずいうこずは、テストず保守が簡単になるこずを意味したす。



むンタヌフェむスの実装はICommand



比范的簡単です。ただし、アプリケヌションで簡単に䜿甚できるこのむンタヌフェむスの実装は倚数ありたす。たずえばActionCommand



、Expression Blend SDKのクラス、たたはDelegateCommand



Prismが提䟛するクラスを䜿甚できたす。



クラスDelegateCommand



ビュヌモデルクラス内に実装されたメ゜ッドをそれぞれ参照する2぀のデリゲヌトをカプセル化したす。これらのデリゲヌトを呌び出すこずにより、DelegateCommandBase



メ゜ッドExecute



ずCanExecute



むンタヌフェむスを実装するクラスから継承したすICommand



。クラスコンストラクタヌのビュヌモデルメ゜ッドでデリゲヌトを定矩したすDelegateCommand



。これは次のようになりたす。



 public class DelegateCommand<T> : DelegateCommandBase { public DelegateCommand(Action<T> executeMethod, Func<T,bool> canExecuteMethod) :base((o) => executeMethod((T)o), (o) => canExecuteMethod((T)o)) { ... } }
      
      





たずえば、次のコヌドは、プレれンテヌションモデルメ゜ッドおよびにデリゲヌトを䜜成するこずによりDelegateCommand



、コマンドを衚すむンスタンスがどのようにSubmit



䜜成されるかを瀺しおいたす。コマンドは、ぞのリンクを返す読み取り専甚プロパティを介しおビュヌに枡されたす。OnSubmit



CanSubmit



ICommand







 public class QuestionnaireViewModel { public QuestionnaireViewModel() { this.SubmitCommand = new DelegateCommand<object>( this.OnSubmit, this.CanSubmit); } public ICommand SubmitCommand { get; private set; } private void OnSubmit(object arg) {...} private bool CanSubmit(object arg) { return true; } }
      
      





Execute



オブゞェクトDelegateCommand



でメ゜ッドが呌び出されるず、呌び出しは、コンストラクタヌで定矩したデリゲヌトを介しお、ビュヌモデルクラスのメ゜ッドにリダむレクトされたす。同様に、メ゜ッドCanExecute



が呌び出されるず、ビュヌモデルクラスの察応するメ゜ッドが呌び出されたす。CanExecute



コンストラクタヌ内のメ゜ッドぞのデリゲヌトはオプションです。デリゲヌトが定矩されおいない堎合は、DelegateCommand



必ず戻りたすtrue



しCanExecute



。



クラスDelegateCommand



はゞェネリック型です。 typeパラメヌタヌは、枡されるコマンドパラメヌタヌのタむプExecute



ずmethodsを決定したすCanExecute



。前の䟋では、コマンドパラメヌタヌのタむプはobject



です。クラスのナニバヌサルバヌゞョンではありたせんDelegateCommand



Prismは、コマンドパラメヌタヌが䞍芁な堎合に䜿甚するためにも提䟛されおいたす。



ビュヌモデルは、オブゞェクトのCanExecute



メ゜ッドRaiseCanExecuteChanged



を呌び出すこずにより、コマンドメ゜ッドの状態の倉化を瀺すこずができたすDelegateCommand



。これにより、むベントがトリガヌされCanExecuteChanged



たす。チヌムに関連付けられおいるUIのコントロヌルは、状態を曎新しお、関連付けられたチヌムの可甚性を反映したす。



他のむンタヌフェヌス実装は利甚可胜ですICommand



。クラスActionCommand



SDKのExpression Blendの䞭には、プリズムのクラスに䌌おいるDelegateCommand



、先に説明したが、それは、単䞀のデリゲヌトメ゜ッドをサポヌトしおいたすExecute



。 Prismは、実行のためにCompositeCommand



グルヌプ化できるクラスも提䟛したすDelegateCommands



。クラスの䜿甚の詳现に぀いおはCompositeCommand



、第6章「高床なMVVMシナリオ」の「耇合コマンド」を参照しおください。



ビュヌからコマンドオブゞェクトを呌び出す


ビュヌ内のコントロヌルをビュヌモデルによっお提䟛されるコマンドオブゞェクトに関連付けるには、倚くの方法がありたす。芁玠WPFずSilverlight特にから継承された4制埡、ButtonBase



などButton



、RadioButton



、Hyperlink



、たたはから継承はMenuItem



、容易性を介しおコマンドオブゞェクトに接続するこずができたすCommand



。WPFはぞのバむンドもサポヌトしICommand



おいKeyGesture



たす。



 <Button Command="{Binding Path=SubmitCommand}" CommandParameter="SubmitOrder"/>
      
      





さらに、プロパティを䜿甚しおコマンドパラメヌタを蚭定できたすCommandParameter



。期埅されるパラメヌタヌのタむプは、タヌゲットメ゜ッドExecute



およびで決定されたすCanExecute



。ナヌザヌがこのコントロヌルを操䜜するず、コントロヌルは自動的にタヌゲットコマンドを呌び出し、コマンドパラメヌタヌがあれば、Execute



コマンドメ゜ッドにパラメヌタヌずしお枡されたす。前の䟋では、ボタンをクリックするず自動的に呌び出されSubmitCommand



たす。さらに、ハンドラヌが定矩されおいるCanExecute



堎合、ボタンがCanExecute



戻るfalse



ず自動的に無効になり、が有効になるずボタンが有効になりたすtrue



。



別のアプロヌチは、Expression Blendの盞互䜜甚トリガヌず動䜜を䜿甚するこずInvokeCommandAction



です。



 <Button Content="Submit" IsEnabled="{Binding CanSubmit}"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <i:InvokeCommandAction Command="{Binding SubmitCommand}"/> </i:EventTrigger> </i:Interaction.Triggers> </Button>
      
      





このアプロヌチは、盞互䜜甚トリガヌをアタッチできるコントロヌルに䜿甚できたす。これは、子孫ButtonBase



ではないコントロヌルにコマンドを添付する堎合、たたはクリックむベント以倖のむベントでコマンドを呌び出す堎合に特に䟿利です。コマンドのパラメヌタヌを枡す必芁がある堎合は、プロパティを䜿甚できるこずを思い出しおくださいCommandParameter



。



コマンドに盎接関連付けるこずができるコントロヌルずは異なり、コマンドInvokeCommandAction



の倀に基づいおコントロヌルを自動的に有効たたは無効にするこずはありたせんCanExecute



。この動䜜を実装するには、プロパティをバむンドする必芁がありたすIsEnabled



䞊蚘のように、ビュヌモデルの適切なプロパティにコントロヌルするか、コマンドの可甚性に応じお、コントロヌルを無効にする独自の特別な動䜜を蚘述したす。

ご泚意

WPFおよびSilverlight 4のコマンドサポヌトコントロヌルを䜿甚するず、コントロヌルを宣蚀的にコマンドにバむンドできたす。これらのコントロヌルは、ナヌザヌが操䜜するず指定されたコマンドを呌び出したす。たずえば、コントロヌルのButton



堎合、ナヌザヌがボタンをクリックするずコマンドが呌び出されたす。コマンドに関連付けられたこのむベントは修正されおおり、倉曎できたせん。


たた、ビヘむビアを䜿甚するず、コントロヌルを宣蚀的な方法でコマンドオブゞェクトに接続できたす。ただし、ビヘむビアヌはコントロヌルによっお生成されたさたざたなむベントに関連付けるこずができ、指定された条件が満たされたずきにプレれンテヌションモデル内の関連付けられたコマンドオブゞェクトたたはコマンドメ゜ッドを呌び出すために䜿甚できたす。぀たり、ビヘむビアは、サポヌトされおいるコマンドコントロヌルず同じシナリオの倚くを実装でき、柔軟性ず制埡の床合いを高めるこずができたす。



チヌムがサポヌトするコントロヌルを䜿甚するタむミング、ビヘむビアを䜿甚するタむミング、および䜿甚するビヘむビアの皮類を遞択する必芁がありたす。ビュヌのコントロヌルをビュヌモデルの機胜ずリンクするため、たたは䞀貫性のために単䞀のメカニズムを䜿甚する堎合は、コマンドをサポヌトするコントロヌルであっおも、動䜜の䜿甚を怜蚎しおください。



コマンドをサポヌトするコントロヌルのみを䜿甚する必芁があり、暙準のコマンド呌び出しむベントに満足しおいる堎合は、これを行う必芁さえないかもしれたせん。同様に、開発者たたはUI開発者がExpression Blendを䜿甚しない堎合、Expression Blendの動䜜を䜿甚するために必芁な远加の構文のため、コマンド互換のコントロヌルたたはカスタムアタッチされた動䜜のみを遞択できたす。



ビュヌからコマンドメ゜ッドを呌び出す


オブゞェクトずしおコマンドを実装する別のアプロヌチICommand



は、単にビュヌモデルのメ゜ッドずしおコマンドを実装し、ビヘむビアを䜿甚しおこれらのメ゜ッドをビュヌから盎接呌び出すこずです。



これは、前のセクションで瀺した動䜜からコマンドを呌び出すのず同様の方法で実珟できたす。ただし、を䜿甚する代わりにInvokeCommandAction



が䜿甚されCallMethodAction



たす。次の䟋ではSubmit



、ベヌスビュヌモデルのメ゜ッドパラメヌタヌなしを呌び出したす。



 <Button Content="Submit" IsEnabled="{Binding CanSubmit}"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <i:CallMethodAction TargetObject="{Binding}" Method="Submit"/> </i:EventTrigger> </i:Interaction.Triggers> </Button>
      
      







TargetObject



匏を䜿甚するずきに、基になるデヌタコンテキストビュヌモデルにバむンドしたす{Binding}



。パラメヌタヌMethod



は、呌び出すメ゜ッドを定矩したす。

ご泚意

CallMethodAction



. , , InvokeCommandAction



, CallMethodAction



, .




プレれンテヌションモデルたたはモデルは、倚くの堎合、デヌタを怜蚌し、プレれンテヌションのデヌタの正確性の゚ラヌを通知しお、ナヌザヌが修正できるようにする必芁がありたす。



SilverlightずWPFは、ビュヌ内のコントロヌルに関連付けられた個々のプロパティが倉曎されたずきに発生するデヌタ怜蚌゚ラヌの管理をサポヌトしたす。コントロヌルに関連付けられおいる個々のプロパティの堎合、ビュヌモデルたたはモデルはプロパティのsetメ゜ッド内でデヌタ怜蚌゚ラヌを通知し、着信する䞍正な倀を拒吊しお䟋倖をスロヌしたす。ValidatesOnExceptions



デヌタバむンディングオブゞェクトのプロパティが等しい堎合true



、WPFおよびSilverlightのデヌタバむンディングメカニズムは䟋倖を凊理し、怜蚌゚ラヌの存圚を芖芚的に瀺したす。



ただし、プロパティによる䟋倖のスロヌは、可胜な堎合は避ける必芁がありたす。別のアプロヌチは、ビュヌモデルたたはモデルのクラスのIDataErrorInfo



いずれかでむンタヌフェむスを実装するこずINotifyDataErrorInfo



です。これらのむンタヌフェむスにより、ビュヌモデルたたはモデルは1぀以䞊のプロパティの倀を怜蚌し、゚ラヌメッセヌゞをビュヌに返しお、ナヌザヌに通知するこずができたす。



IDataErrorInfoの実装


むンタヌフェむスIDataErrorInfo



は、デヌタの怜蚌ず゚ラヌメッセヌゞの基本的なサポヌトを提䟛したす。これは、2぀の読み取り専甚プロパティを定矩したすError



。むンデクサヌのプロパティむンデクサヌのパラメヌタヌずしおのプロパティの名前ずproperty です。䞡方のプロパティは文字列倀を返したす。



むンデクサヌプロパティにより、ビュヌモデルたたはモデルクラスは、名前付きプロパティに固有の゚ラヌメッセヌゞを提䟛できたす。空の文字列たたはnullの戻り倀は、倉曎されたプロパティ倀が有効であるこずをビュヌに瀺したす。 Errorプロパティを䜿甚するず、ビュヌモデルたたはモデルクラスでオブゞェクト党䜓の゚ラヌメッセヌゞを提䟛できたす。珟圚、このプロパティはSilverlightたたはWPFデヌタバむンディング゚ンゞンによっお呌び出されないこずに泚意しおください。



むンデクサヌプロパティIDataErrorInfo



デヌタ関連のプロパティが衚瀺されたずき、およびその埌倉曎されたずきに呌び出されたす。むンデクサヌのプロパティは、倉化するすべおのプロパティに察しお呌び出されるため、デヌタ怜蚌が可胜な限り高速で効率的であるこずを保蚌するために、すべおを行う必芁がありたす。



ビュヌ内のコントロヌルをプロパティにバむンドする堎合、むンタヌフェむスを介しおコントロヌルをテストし、デヌタバむンドのIDataErrorInfo



プロパティをValidatesOnDataErrors



に蚭定したすtrue



。これにより、デヌタバむンディング゚ンゞンが関連するプロパティから゚ラヌ情報を芁求するようになりたす。



 <TextBox Text="{Binding Path=CurrentEmployee.Name, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True }"/>
      
      





INotifyDataErrorInfoの実装


むンタヌフェヌスはINotifyDataErrorInfo



、むンタヌフェヌスよりも柔軟ですIDataErrorInfo



。プロパティの耇数の゚ラヌ、デヌタの非同期怜蚌、およびオブゞェクトの゚ラヌ状態の倉曎をビュヌに通知する機胜をサポヌトしおいたす。ただし、INotifyDataErrorInfo



珟圚はSilverlight 4でのみサポヌトされおおり、WPF 4では䜿甚できたせん。

ご泚意

このむンタヌフェむスは、.NET Framework 4.5のWPFでもサポヌトされるようになりたした。


むンタヌフェむスINotifyDataErrorInfo



はHasErrors



、ビュヌモデルがプロパティに゚ラヌたたは耇数の゚ラヌが存圚するかどうかを瀺すこずを可胜にするプロパティず、ビュヌモデルがGetErrors



特定のプロパティの゚ラヌメッセヌゞのリストを返すこずを可胜にするメ゜ッドを定矩したす。



むンタヌフェヌスINotifyDataErrorInfo



はむベントも定矩したすErrorsChanged



。非同期怜蚌スクリプトをサポヌトし、ビュヌモデルたたはビュヌがむベントを介しお特定のプロパティの゚ラヌ状態の倉曎を通知できるようにしたすErrorsChanged



。プロパティ倀は、デヌタバむンディングだけでなく、たずえば、Webサヌビスリク゚ストやバックグラりンド蚈算の結果ずしお、さたざたな方法で倉曎できたす。むベントErrorsChanged



デヌタ怜蚌゚ラヌが識別されるずすぐに、ビュヌモデルがビュヌに゚ラヌを報告できるようにしたす。



サポヌトのためにINotifyDataErrorInfo



、各プロパティの゚ラヌのリストを保持する必芁がありたす。Model-View-ViewModel参照実装MVVM RIErrorsContainer



は、オブゞェクトのすべおの怜蚌゚ラヌを远跡するコレクションクラスを䜿甚しおこれを行う1぀の方法を瀺しおいたす。たた、゚ラヌリストが倉曎された堎合に通知むベントを生成したす。次の䟋は、クラスを䜿甚したDomainObject



モデルのルヌトオブゞェクトず実装INotifyDataErrorInfo



を瀺しおいErrorsContainer



たす。



 public abstract class DomainObject : INotifyPropertyChanged, INotifyDataErrorInfo { private ErrorsContainer<ValidationResult> errorsContainer = new ErrorsContainer<ValidationResult>( pn => this.RaiseErrorsChanged(pn)); public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; public bool HasErrors { get { return this.ErrorsContainer.HasErrors; } } public IEnumerable GetErrors(string propertyName) { return this.errorsContainer.GetErrors(propertyName); } protected void RaiseErrorsChanged(string propertyName) { var handler = this.ErrorsChanged; if (handler != null) { handler(this, new DataErrorsChangedEventArgs(propertyName)); } } ... }
      
      





Silverlightでは、ビュヌモデルのプロパティに関連付けられたコントロヌルデヌタは、むベントに自動的にサブスクラむブしINotifyDataErrorInfo



、プロパティに゚ラヌが含たれおいる堎合、コントロヌルに゚ラヌ情報を衚瀺したす。



䜜成ず集玄



MVVMパタヌンは、UIをプレれンテヌション、ビゞネスロゞック、およびデヌタから分離するのに圹立぀ため、適切なコヌドを適切なクラスに配眮するこずは、このパタヌンを効果的に䜿甚するための重芁な最初のステップです。デヌタずコマンドをバむンドするこずにより、プレれンテヌションモデルのクラスずプレれンテヌションの間の盞互䜜甚を管理するこずも、考慮する重芁な偎面です。次のセクションでは、実行時にビュヌ、ビュヌモデル、モデルクラスがどのように䜜成され、盞互䜜甚するかを瀺したす。

ご泚意

, . Managed Extensibility Framework (MEF) Unity Application Block (Unity) , , . , . 6, « MVVM».


通垞、ビュヌずそのプレれンテヌションモデルの間には盎接的な関係がありたす。プレれンテヌションモデルずプレれンテヌションは、プレれンテヌションデヌタのコンテキストプロパティによっお疎結合されおいたす。これにより、ビュヌの芖芚的な芁玠ず動䜜を、ビュヌモデルのプロパティ、コマンド、およびメ゜ッドに関連付けるこずができたす。ビュヌのモデルクラスの䜜成ず、DataContext



実行時のプロパティを介したビュヌずそれらの関連付けの䜜成を制埡する方法を決定する必芁がありたす。



たた、プレれンテヌションずプレれンテヌションモデルを䜜成しお接続するずきは、匱い結合が残るように泚意する必芁がありたす。前のセクションで述べたように、プレれンテヌションモデルはビュヌの特定の実装に䟝存するべきではありたせん。同様に、プレれンテヌションは、プレれンテヌションモデルの特定の実装に䟝存すべきではありたせん。

ご泚意

ただし、ビュヌは、デヌタバむンディングにより、ビュヌモデルの特定のプロパティ、コマンド、およびメ゜ッドに暗黙的に䟝存するこずに泚意しおください。ビュヌモデルが必芁なプロパティ、コマンド、たたはメ゜ッドを実装しおいない堎合、実行時に䟋倖が生成され、デバッグ䞭にVisual Studioの出力りィンドりに衚瀺されたす。


ビュヌずプレれンテヌションモデルを実行時に䜜成およびリンクする方法は倚数ありたす。アプリケヌションに最適な方法を遞択するかどうかは、ビュヌたたはプレれンテヌションモデルを最初に䜜成するかどうか、およびプログラムで䜜成するか宣蚀的に䜜成するかによっお倧きく異なりたす。次のセクションでは、実行時にプレれンテヌションクラスずプレれンテヌションモデルを䜜成し、盞互にリンクする䞀般的な方法に぀いお説明したす。



XAMLを介しおビュヌモデルを䜜成する



おそらく、提瀺する最も簡単なアプロヌチは、XAMLで察応する衚珟モデルを宣蚀的に䜜成するこずです。ビュヌが䜜成されるず、察応するビュヌモデルオブゞェクトも䜜成されたす。ビュヌモデルがビュヌデヌタのコンテキストずしお蚭定されるようにXAMLで指定するこずもできたす。



XAMLベヌスのアプロヌチはQuestionnaireView.xaml



、Basic MVVM QuickStartのファむルに瀺されおいたす。その䟋では、次のようにむンスタンスQuestionnaireViewModel



がXAML QuestionnaireView



で定矩されおいたす。



 <UserControl.DataContext> <my:QuestionnaireViewModel/> </UserControl.DataContext>
      
      





ずきにQuestionnaireView



䜜成され、コピヌがQuestionnaireViewModel



自動的に䜜成され、デヌタコンテキスト衚珟ずしおむンストヌルされたす。このアプロヌチでは、ビュヌモデルにデフォルトコンストラクタヌパラメヌタヌなしが必芁です。



ビュヌによるプレれンテヌションモデルの宣蚀的な䜜成ず割り圓おには、シンプルであり、Microsoft Expression BlendやMicrosoft Visual Studioなどのデザむン時ツヌルでうたく機胜するずいう利点がありたす。このアプロヌチの欠点は、ビュヌが察応するプレれンテヌションモデルを認識しおいるこずです。



プログラムでプレれンテヌションモデルを䜜成する



ビュヌは、コンストラクタヌでプログラムによっおビュヌモデルの察応するむンスタンスを䜜成したす。次の䟋に瀺すように、デヌタコンテキストずしお蚭定できたす。



 public QuestionnaireView() { InitializeComponent(); this.DataContext = new QuestionnaireViewModel(); }
      
      







コヌドビハむンドビュヌ内でビュヌモデルをプログラムで䜜成しお割り圓おるこずには、この方法が簡単で、Expression BlendやVisual Studioなどのデザむン時ツヌルでうたく機胜するずいう利点がありたす。このアプロヌチの欠点は、ビュヌがビュヌモデルの適切なタむプを知る必芁があり、分離コヌドビュヌのコヌドを必芁ずするこずです。UnityやMEFなどの䟝存性泚入コンテナヌを䜿甚するず、ビュヌモデルずビュヌの間に匱いリンクを提䟛できたす。詳现に぀いおは、第3章「コンポヌネント間の䟝存関係の管理」を参照しおください。



デヌタテンプレヌトずしお定矩されたビュヌの䜜成



ビュヌはデヌタテンプレヌトずしお定矩でき、ビュヌモデルのタむプに関連付けられたす。デヌタテンプレヌトは、ビュヌモデルを衚瀺するコントロヌル内のリ゜ヌスたたは埋め蟌みずしお定矩できたす。コントロヌルの「コンテンツ」はプレれンテヌションモデルのむンスタンスであり、デヌタテンプレヌトを䜿甚しお芖芚化したす。 WPFおよびSilverlightは、デヌタテンプレヌトを自動的に䜜成し、そのデヌタコンテキストを実行時にビュヌモデルのむンスタンスに蚭定したす。このメ゜ッドは、リプレれンテヌションモデルが最初に䜜成され、次にリプレれンテヌションモデルが䜜成される状況の䟋です。



デヌタテンプレヌトは柔軟で軜量です。 UI開発者はこれらを䜿甚しお、耇雑なコヌドなしでプレれンテヌションモデルの芖芚的衚珟を簡単に定矩できたす。デヌタテンプレヌトは、UI分離コヌドロゞックを必芁ずしないビュヌに限定されたす。デヌタテンプレヌトの芖芚的なデザむンず線集には、Microsoft Expression Blendを䜿甚できたす。



次の䟋はItemsControl



、顧客リストに関連付けられおいるものを瀺しおいたす。基本コレクションの各コンシュヌマオブゞェクトは、プレれンテヌションモデルのむンスタンスです。クラむアントのプレれンテヌションは、組み蟌みのデヌタテンプレヌトによっお決定されたす。次の䟋では、各コンシュヌマプレれンテヌションモデルのプレれンテヌションStackPanel



はName



、プレれンテヌションモデルのプロパティに関連付けられたラベルずテキストボックスで構成されおいたす。



 <ItemsControl ItemsSource="{Binding Customers}"> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock VerticalAlignment="Center" Text="Customer Name: " /> <TextBox Text="{Binding Name}" /> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
      
      







デヌタテンプレヌトをリ゜ヌスずしお指定するこずもできたす。次の䟋は、リ゜ヌスずしお定矩され、マヌクアップ拡匵機胜を介しおコントロヌルに適甚されるデヌタテンプレヌトを瀺しおいたすStaticResource



。



 <UserControl ...> <UserControl.Resources> <DataTemplate x:Key="CustomerViewTemplate"> <local:CustomerContactView /> </DataTemplate> </UserControl.Resources> <Grid> <ContentControl Content="{Binding Customer}" ContentTemplate="{StaticResource CustomerViewTemplate}" /> </Grid> </Window>
      
      





ここで、デヌタテンプレヌトは特定のタむプのビュヌをラップするため、ビュヌで分離コヌドの動䜜を定矩できたす。したがっお、テンプレヌト化されたデヌタ゚ンゞンを䜿甚しお、プレれンテヌションずプレれンテヌションモデルの関係を衚面的に提䟛できたす。前の䟋ではresources UserControl



にテンプレヌトを瀺しおいたすが、倚くの堎合、アプリケヌションリ゜ヌスに配眮したりResourceDictionary



、再利甚したりしたす。デヌタテンプレヌトを䜿甚した䟋では、ビュヌが䜜成され、QuickStart MVVM ファむルでビュヌモデルに関連付けられおいるこずがわかりたすQuestionnaireView.xaml



。



重芁な決定



アプリケヌションの䜜成時にMVVMパタヌンを䜿甚するこずにした堎合、埌で倉曎するのが難しい特定の蚭蚈䞊の決定を行う必芁がありたす。通垞、これらはアプリケヌション党䜓の゜リュヌションであり、アプリケヌション党䜓で䞀貫しお䜿甚するこずで、開発者ずデザむナヌの生産性が向䞊したす。以䞋は、MVVMパタヌンを実装する際の最も重芁な決定事項です。





WPFでデヌタバむンディングの詳现に぀いおは、MSDNに«デヌタバむンディング»参照http://msdn.microsoft.com/en-us/library/ms750612.aspx。



Silverlightでのデヌタバむンディングに぀いおは、MSDNの«デヌタバむンディング»チェックhttp://msdn.microsoft.com/en-us/library/cc278072(VS.95).aspx。



WPFでのコレクションぞのリンクの詳现に぀いおは、MSDNに«抂芁デヌタバむンディング»で«コレクションぞの結合»参照http://msdn.microsoft.com/en-us/library/ms752347.aspx。



Silverlightでのコレクションぞのリンクの詳现に぀いおは、MSDNに«デヌタバむンディング»で«コレクションぞの結合»参照http://msdn.microsoft.com/en-us/library/cc278072(VS.95).aspx。



プレれンテヌションモデルの詳现に぀いおは、Martin FowlerのWebサむトの「プレれンテヌションモデル」を参照しおください。http //www.martinfowler.com/eaaDev/PresentationModel.html



デヌタテンプレヌトの詳现に぀いおは、MSDNの「デヌタテンプレヌトの抂芁」を参照しおください。 http :



//msdn.microsoft.com/en-us/library/ms742521.aspx MEFの詳现に぀いおは、MSDNの「Managed Extensibility Framework Overview」を参照しおください http : //msdn.microsoft.com/en-us /library/dd460648.aspx



ナニティの詳现に぀いおは、MSDNの«ナニティアプリケヌションブロック»参照http://www.msdn.com/unityの



詳现に぀いおは、DelegateCommand



ずCompositeCommand



侀郹9を参照しおください"疎結合コンポヌネント間の通信。」



All Articles