Model-View-ViewModelアーキテクチャWPFアプリケーションでViewModelを実装する場合、データバインド可能にする方法には2つの主要な選択肢があるようです。ビューがバインドするプロパティにDependencyProperty
を使用する実装を見てきましたが、代わりにINotifyPropertyChanged
を実装するViewModelを見てきました。
私の質問は、いつどちらを優先するかです。パフォーマンスの違いはありますか? ViewModel依存関係をWPFに提供することは本当に良い考えですか?設計を決定するとき、他に何を考慮する必要がありますか?
ケントは、このトピックに関する興味深いブログを書きました: 表示モデル:POCOとDependencyObjects 。
概要:
私はPOCOアプローチを好みます。 INotifyPropertyChangedインターフェイスを実装するPresentationModel(別名ViewModel)の基本クラスは、次の場所にあります。 http://compositeextensions.codeplex.com
WPFパフォーマンスガイドによると、DependencyObjectsはINotifyPropertyChangedを実装するPOCOよりも確実に優れたパフォーマンスを発揮します。
選択は、ビジネスロジックとUI抽象化レベルに完全に基づいています。適切な分離が必要ない場合は、DPが有効です。
DependencyPropertiesは主にVisualElementsレベルで適用されるため、ビジネス要件ごとに多数のDPを作成するのは得策ではありません。また、DPにはINotifyPropertyChangedよりも大きなコストがかかります。 WPF/Silverlightを設計するときは、UIとViewModelを完全に分離して、いつでもレイアウトとUIコントロールを変更できるようにします(テーマとスタイルに基づいて)
この投稿も参照してください- https://stackoverflow.com/questions/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel リンクには、Model-View-ViewModelパターンへの多くの参照があります。これは、この説明に非常に関連しています。
表現力の観点から、私は依存関係プロパティの使用を楽しんでおり、INotifyPropertyChanged
の考え方に夢中になっています。 string
プロパティ名とイベントサブスクリプションによるメモリリークの可能性は別として、INotifyPropertyChanged
はより明確なメカニズムです。
依存関係のプロパティは、簡単に理解できる静的メタデータを使用して、「これを行うとき」を意味します。それは宣言的なアプローチであり、優雅さに対する私の票を獲得します。
依存関係プロパティは、データバインディングのソースとしてではなく、UI要素での(ターゲットとしての)バインディングをサポートすることを目的としています。これがINotifyPropertyの出番です。純粋な観点から、ViewModelsでDPを使用しないでください。
「バインディングのソースになるために、プロパティは依存関係プロパティである必要はありません。任意のCLRプロパティをバインディングソースとして使用できます。ただし、バインディングのターゲットになるためには、プロパティが依存関係プロパティ:一方向または双方向のバインディングを有効にするには、ソースプロパティがバインディングシステム、したがってターゲットに伝播する変更通知をサポートする必要があります。カスタムCLRバインディングソースの場合、これはプロパティがINotifyPropertyChangedをサポートする必要があることを意味します。コレクションはINotifyCollectionChangedをサポートする必要があります。」
すべての依存関係オブジェクトをシリアル化することはできません(これにより、ViewModelおよびDTO(POCO)の使用が妨げられる可能性があります。
Silverlight内のDPとWPFには違いがあります。
http://msdn.Microsoft.com/en-us/library/cc221408(v = VS.95).aspx
http://msdn.Microsoft.com/en-us/library/cc903933(VS.95).aspx
INotifyPropertyChanged
を使用すると、プロパティのゲッターとセッターのコードにロジックを追加することもできます。
DependencyProperty
の例:
public static DependencyProperty NameProperty = DependencyProperty.Register( "Name", typeof( String), typeof( Customer ) );
public String Name
{
set { SetValue( NameProperty, value ); }
get { return ( String ) GetValue( NameProperty ); }
}
ゲッターとセッターでは、それぞれSetValueとGetValueを呼び出すだけです。フレームワークの他の部分では、ゲッター/セッターは呼び出されず、代わりにSetValue、GetValueを直接呼び出すため、プロパティロジックは確実に実行されます。
INotifyPropertyChanged
を使用して、イベントを定義します。
public event PropertyChangedEventHandler PropertyChanged;
そして、コード内の任意の場所に任意のロジックを配置し、次を呼び出します。
// ...
// Something cool...
// ...
if( this.PropertyChanged != null )
{
PropertyChanged( this, new PropertyChangedEventArgs( "Name" ) );
}
// More cool stuff that will reliably happen...
これは、ゲッター/セッター、またはその他の場所にあります。
私も最近この決定を検討しなければなりませんでした。
INotifyPropertyChangedメカニズムは、状態を複製することなくGUIを既存のビジネスロジックフレームワークに接着できるため、ニーズに適していることがわかりました。私が使用していたフレームワークには独自のオブザーバーパターンがあり、あるレベルの通知を次のレベルに簡単に転送できました。ビジネスロジックフレームワークのオブザーバーインターフェイスとINotifyPropertyChangedインターフェイスを実装したクラスがありました。
DPでは、状態を自分で保存するバックエンドを定義できません。私がバインドしていた状態のすべての項目のコピーを.netにキャッシュさせなければならなかっただろう。これは不必要なオーバーヘッドのように思えました-私の状態は大きく複雑です。
そのため、ここでは、ビジネスロジックからGUIにプロパティを公開するためのINotifyPropertyChangedの方が優れていることがわかりました。
プロパティを公開し、そのプロパティへの変更が他のGUIウィジェットDPに影響を与えるためにカスタムGUIウィジェットが必要だったということは、シンプルなソリューションを証明しました。
そこで、GUIからGUIへの通知にDPが役立つことがわかりました。
ViewModel依存関係をWPFに提供することは本当に良い考えですか?
.NET 4.0にはSystem.Xaml.dllが含まれるので、それを利用するために任意のフレームワークに依存する必要はありません。 Rob Relyea's のPDCセッションに関する投稿を参照してください。
マイテイク
XAMLはオブジェクトを記述するための言語であり、WPFは記述されたオブジェクトがUI要素であるフレームワークです。
それらの関係は、ロジックを記述するための言語であるC#と、特定の種類のロジックを実装するフレームワークである.NETに似ています。
XAMLの目的は、宣言的なオブジェクトグラフです。 W * Fテクノロジーはこのパラダイムの優れた候補ですが、XAMLはそれらとは独立して存在します。
XAMLと依存関係システム全体はWFとWPFの個別のスタックとして実装され、おそらくそれらの間に依存関係(しゃれなし)を作成せずに異なるチームの経験を活用します。
依存関係プロパティは、カスタムコントロール作成の接着剤です。 Intelli-senseを使用してXAML設計時にプロパティウィンドウにプロパティを表示することに関心がある場合は、依存関係プロパティを使用する必要があります。 INPCは設計時にプロパティウィンドウにプロパティを表示しません。
ボタンなどの作成するコントロールでは、依存関係プロパティを使用する必要があるようです。 XAMLでプロパティを使用し、すべてのWPF機能を使用するには、それらのプロパティが依存関係プロパティである必要があります。
ただし、ViewModelはINotifyPropertyChangedを使用することをお勧めします。 INotifyPropertyChangedを使用すると、必要に応じてゲッター/セッターロジックを使用できるようになります。
INotifyPropertyChangedを既に実装しているViewModelの基本クラスのJosh Smithのバージョンを確認することをお勧めします。
http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/
これは、ViewModelの実行方法の優れた例だと思います。
Bindingの2つの異なることにDependencyPropertyとINotifyPropertyChangedが使用されていると思います。最初はプロパティをバインディングのターゲットにし、別のプロパティから入力を受け取るためです({Binding ...}を使用してプロパティを設定します)。プロパティの値をバインディング(バインディングパス式の名前)のソースとして使用する場合。したがって、選択は単に技術的なものです。
DependencyObject
を好む理由は1つだけです-バインディングの方がうまく機能します。 ListBox
とTextBox
の例を試して、INotifyPropertyChanged
プロパティとDependencyProperty
のデータをリストに追加し、TextBox
から現在のアイテムを編集します。
INotifyPropertyChangedのないプレゼンテーションモデル でブログを書いた、より直接的なアプローチを好みます。データバインディングの代わりに、ブックキーピングコードなしでCLRプロパティに直接バインドできます。 View Modelで昔ながらの.NETコードを書くだけで、Data Modelが変更されると更新されます。
プロパティを他のコントロールに公開したい場合は、依存関係プロパティを使用する必要があります...しかし、幸運を見つけるには時間がかかります...