[解決済み] WPFのdependencyプロパティとattachedプロパティの違いは何ですか?
質問
WPFの(カスタム)依存性プロパティとattachedプロパティの違いは何ですか? それぞれどのような用途がありますか? 一般的に、実装はどのように違うのでしょうか?
どのように解決するのですか?
概要
この件に関するドキュメントがほとんどなかったため、いくつかの方法で ソース コード を突き合わせる必要がありましたが、ここに答えがあります。
依存性プロパティを通常のプロパティとして登録することと、アタッチドプロパティとして登録することの違いは、"哲学的なもの以外に、(
通常のプロパティは宣言する型とその派生型によって使用されることを意図しており、アタッチドプロパティは任意の
DependencyObject
インスタンス
というのも、@ReedCopsey さんの回答に対するコメントで @MarqueIV さんが気づいたように、通常のプロパティでも任意の
DependencyObject
インスタンスで使用することができます。
さらに、attachedプロパティがquot;type of dependency property"であると述べている他の回答には同意しかねます。フレームワークは、プロパティがアタッチされたものとして登録されたかどうかを気にしませんし、判断することさえできません(この情報は記録されないという意味で、無関係だからです)。実際には、すべてのプロパティは、それらが添付されたプロパティであるかのように登録されますが、通常のものの場合には、それらの動作をわずかに変更するいくつかの追加的なことが行われます。
コードの抜粋
自分でソースコードを調べる手間を省くために、ここでは何が起こるかを要約して説明します。
メタデータを指定せずにプロパティを登録する場合、以下のように呼び出します。
DependencyProperty.Register(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass))
収量 全く同じ を呼び出すのと同じ結果になります。
DependencyProperty.RegisterAttached(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass))
ただし、メタデータを指定する際に
DependencyProperty.Register(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass),
typeMetadata: new FrameworkPropertyMetadata
{
CoerceValueCallback = CoerceCallback,
DefaultValue = "default value",
PropertyChangedCallback = ChangedCallback
});
を呼び出すことと同じです。
var property = DependencyProperty.RegisterAttached(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass),
defaultMetadata: new PropertyMetadata
{
DefaultValue = "default value",
});
property.OverrideMetadata(
forType: typeof(MyClass),
typeMetadata: new FrameworkPropertyMetadata
{
CoerceValueCallback = CoerceCallback,
DefaultValue = "default value",
PropertyChangedCallback = ChangedCallback
});
結論
通常の依存性プロパティとアタッチされた依存性プロパティの間の重要な(そして唯一の)違いは、デフォルトのメタデータが DependencyProperty.DefaultMetadata プロパティで利用できるデフォルトのメタデータです。これは 備考 セクションを作成します。
非アタッチドプロパティでは、このプロパティによって返されるメタデータタイプは、以下の派生タイプにキャストすることはできません。 プロパティメターデータ タイプにキャストすることはできません。元々登録されていたメタデータを、そのオリジナルの派生メタデータ・タイプも含めて利用したい場合は GetMetadata(Type) を呼び、パラメータとしてオリジナルの登録タイプを渡します。
アタッチされたプロパティの場合、このプロパティによって返されるメタデータのタイプは、オリジナルの RegisterAttached 登録メソッドで指定されたタイプと一致します。
これは提供されたコードにはっきりと現れています。小さなヒントは、登録メソッドにも隠されています。
RegisterAttached
の場合、メタデータ・パラメータは
defaultMetadata
という名前になりますが、一方
Register
という名前になります。
typeMetadata
. アタッチドプロパティでは、提供されたメタデータがデフォルトのメタデータになります。しかし、通常のプロパティの場合、デフォルトのメタデータは常に新しいインスタンスの
PropertyMetadata
のみで構成されます。
DefaultValue
だけが設定されています (提供されたメタデータから、あるいは自動的に)。への呼び出しのみです。
OverrideMetadata
の呼び出しだけが、提供されたメタデータを実際に使用します。
結果
主な実用上の違いは、通常のプロパティの場合は
CoerceValueCallback
と
PropertyChangedCallback
が該当します。
のみ
はオーナー型として宣言された型から派生した型に対して適用され、 アタッチされたプロパティに対しては
すべて
型に適用されます。例えば、このシナリオの場合
var d = new DependencyObject();
d.SetValue(SomeClass.SomeProperty, "some value");
登録されている
PropertyChangedCallback
と呼ばれることになります。
がアタッチド・プロパティとして登録された場合、しかし
は呼び出されません。
と呼ばれることはありません。同じことが
CoerceValueCallback
.
二次的な違いは
OverrideMetadata
は供給された型が
DependencyObject
. 実際には、通常のプロパティのオーナータイプは
を導出しなければなりません。
から
DependencyObject
であるのに対し、アタッチドプロパティでは
のいずれかになります。
型(静的クラス、構造体、列挙型、デリゲートなどを含む)であることができます。
補足
MarqueIV さんの提案以外にも、通常のプロパティとアタッチドプロパティの使い分けは XAML . つまり、通常のプロパティは暗黙的な名前構文を必要とし、attachedプロパティは明示的な名前構文を必要とするということです。これは技術的には ではありません。 ですが、実際には通常そうです。分かりやすくするために
<!-- Implicit property name -->
<ns:SomeClass SomeProperty="some value" />
<!-- Explicit property name -->
<DependencyObject ns:SomeClass.SomeProperty="some value" />
で 純粋なXAML では、これらの構文の使用を統制する唯一のルールは以下の通りです。
- 暗黙の名前構文は、要素 の場合のみ使用できます。 この要素が表すクラスが CLR という名前のプロパティがあります。
- 明示的な名前構文は要素で使用可能 の場合のみ 完全な名前の最初の部分によって指定されたクラスが、適切な静的な を取得します。 / セット メソッド(以下 アクセサ と呼ばれる) で、フルネームの2番目の部分と一致する名前を持つ。
これらの条件を満たすことで、バッキング依存性プロパティがregularとattachedのどちらで登録されていても、対応する構文が使用できるようになります。
今述べた誤解は、大多数のチュートリアルが (純正の Visual Studio のコード スニペットとともに) CLR プロパティを使用し、アタッチされたプロパティには get/set アクセサを使用するように指示します。しかし、同時に両方を使用することを妨げるものは何もなく、好きな構文を使用することができます。
関連
-
[解決済み] C#のStringとstringの違いは何ですか?
-
[解決済み] C#の正しいバージョン番号を教えてください。
-
[解決済み] ディープクローンオブジェクト
-
[解決済み] .NETでのdecimal, float, doubleの違い?
-
[解決済み] C#のconstとreadonlyの違いは何ですか?
-
[解決済み] .NET Coreと.NET Standard Class Libraryのプロジェクトタイプの違いは何ですか?
-
[解決済み] .NETにおけるstructとclassの違いは何ですか?
-
[解決済み] C#の文字列の前にある@は何ですか?
-
[解決済み] WPFのStaticResourceとDynamicResourceの違いは何ですか?
-
[解決済み】Invoke()とBeginInvoke()の違いは何ですか?)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Microsoft.Practices.ServiceLocationはどこから来たのですか?
-
[解決済み] VB.NETでプログラムパスを取得する?
-
[解決済み] Marginのプロパティ順
-
[解決済み] BasicHttpsBindingとWsHttpBinding with Transport securityの違いは何ですか?
-
[解決済み] AssemblyInfo.csは何に使うのですか?
-
[解決済み] 'Newtonsoft.Json' には 'Microsoft.CSharp' の依存関係がすでに定義されています。
-
[解決済み] ファイルまたはアセンブリをロードできませんでした 操作がサポートされていません。(HRESULT: 0x80131515 からの例外)
-
[解決済み] Nuget接続の試行に失敗しました。"Unable to load service index for source"。
-
[解決済み] LINQクエリでToList()とToArray()のどちらを呼び出すのが良いですか?
-
[解決済み] Microsoft.ACE.OLEDB.12.0' プロバイダがローカルマシンに登録されていません。