INotifyPropertyChangedとViewModelのDependencyProperty
-
08-07-2019 - |
質問
Model-View-ViewModelアーキテクチャのWPFアプリケーションでViewModelを実装する場合、データバインド可能にする方法には2つの主要な選択肢があるようです。ビューがバインドするプロパティに DependencyProperty
を使用する実装を見てきましたが、代わりに INotifyPropertyChanged
を実装するViewModelを見てきました。
私の質問は、いつどちらを優先するかです。パフォーマンスの違いはありますか? ViewModelの依存関係をWPFに与えることは本当に良い考えですか?設計を決定する際、他に何を考慮する必要がありますか?
解決
Kentはこのトピックに関する興味深いブログを書いています。モデルを表示:POCOとDependencyObjects 。
要約:
- DependencyObjectsとしてマークされていません シリアライズ可能
- DependencyObjectクラスは、Equals()および GetHashCode()メソッド
- DependencyObjectにはスレッドアフィニティがあり、アクセスのみ可能 それがあったスレッド上 作成済み
私は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
はより明確なメカニズムです。
依存関係プロパティは、「これが行われたときに、それを行う」ことを意味します。簡単に理解できる静的メタデータを使用します。これは宣言型のアプローチであり、優雅さに投票します。
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...
これはゲッター/セッター、またはその他の場所にある可能性があります。
依存関係プロパティは、データバインディングのソースとしてではなく、UI要素での(ターゲットとしての)バインディングをサポートすることを目的としています。ここでINotifyPropertyが登場します。
"バインディングのソースであるために、プロパティは依存関係プロパティである必要はありません。任意のCLRプロパティをバインディングソースとして使用できます。ただし、バインディングのターゲットになるためには、プロパティは依存関係プロパティである必要があります。一方向または双方向のバインディングを有効にするには、ソースプロパティが、バインディングシステム、したがってターゲットに伝播する変更通知をサポートする必要があります。カスタムCLRバインディングソースの場合、これはプロパティがINotifyPropertyChangedをサポートする必要があることを意味します。コレクションはINotifyCollectionChangedをサポートする必要があります。"
すべての依存関係オブジェクトをシリアル化することはできません(これにより、ViewModelおよびDTO(POCO)の使用が妨げられる可能性があります。
WPFと比較してSilverlight内のDPには違いがあります。
http://msdn.microsoft.com /en-us/library/cc221408(v=VS.95).aspx
http://msdn.microsoft.com/en -us / library / cc903933(VS.95).aspx
私も最近この決定を検討しなければなりませんでした。
私は、状態を複製せずにGUIを既存のビジネスロジックフレームワークに接着できるため、INotifyPropertyChangedメカニズムが私のニーズにより適していることを発見しました。私が使用していたフレームワークには独自のオブザーバーパターンがあり、あるレベルの通知を次のレベルに簡単に転送できました。ビジネスロジックフレームワークのオブザーバーインターフェイスとINotifyPropertyChangedインターフェイスを実装したクラスがありました。
DPでは、状態を自分で保存するバックエンドを定義できません。バインドしていた状態のすべてのアイテムのコピーを.netにキャッシュさせる必要があったでしょう。これは不必要なオーバーヘッドのように思えました-私の状態は大きく複雑です。
ここで、ビジネスロジックからGUIにプロパティを公開するために、ここでINotifyPropertyChangedを見つけました。
それは、プロパティを公開するためにカスタムGUIウィジェットが必要な場所であり、そのプロパティの変更が他のGUIウィジェットに影響を与えると言われたことは、DPがシンプルなソリューションであることを証明しました。
それで、GUIからGUIへの通知にDPが役立つことがわかりました。
ViewModelの依存関係をWPFに与えることは本当に良い考えですか?
.NET 4.0にはSystem.Xaml.dllがあるため、それを利用するために任意のフレームワークに依存する必要はありません。 Rob Relyeaの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の基本クラスのバージョンを確認することをお勧めします。
これは、ViewModelの実行方法の優れた例だと思います。
DependencyPropertyとINotifyPropertyChangedは、Bindingの2つの異なる目的に使用されると思います。1つは、プロパティをバインディングのターゲットにし、別のプロパティから入力を受け取るためです({Binding ...}を使用してプロパティを設定します) 、プロパティの値をバインディング(バインディングパス式の名前)のソースとして使用する場合の最後。 そのため、選択は単に技術的なものです。
INotifyPropertyChangedを使用しないプレゼンテーションモデルでブログを書いた、より直接的なアプローチを好みます。データバインディングの代わりに、簿記コードなしでCLRプロパティに直接バインドできます。ビューモデルで単純な古い.NETコードを記述するだけで、データモデルが変更されると更新されます。
DependencyObject
を好む理由は1つだけです-バインディングの方がうまく機能します。 ListBox
と TextBox
の例を試して、 INotifyPropertyChanged
プロパティと DependencyProperty
のデータをリストに追加して編集します TextBox
...
他のコントロールにプロパティを公開する場合は、依存関係プロパティを使用する必要があります...しかし、幸運なことに、それらを理解するにはしばらく時間がかかるので...