次の方法で共有


依存関係プロパティのメタデータ

Windows Presentation Foundation (WPF) プロパティ システムには、依存関係プロパティ メタデータ レポート システムが含まれています。 メタデータ レポート システムで使用できる情報は、リフレクションまたは一般的な共通言語ランタイム (CLR) の特性を介して使用できる情報を超えています。 依存関係プロパティを登録するときは、メタデータを作成して割り当てるオプションがあります。 依存関係プロパティを定義するクラスから派生した場合は、継承された依存関係プロパティのメタデータをオーバーライドできます。 また、クラスを依存関係プロパティの所有者として追加する場合は、継承された依存関係プロパティのメタデータをオーバーライドできます。

[前提条件]

この記事では、依存関係プロパティの基本的な知識と、依存関係プロパティの概要読んだことを前提としています。 この記事の例に従うには、拡張アプリケーション マークアップ言語 (XAML) に慣れている場合や、WPF アプリケーションを記述する方法を理解している場合に役立ちます。

メタデータの使用方法

依存関係プロパティのメタデータを照会して、依存関係プロパティの特性を調べることができます。 プロパティ システムは、依存関係プロパティを処理するときに、そのメタデータにアクセスします。 依存関係プロパティのメタデータ オブジェクトには、次の種類の情報が含まれています。

  • 依存関係プロパティの既定値。ローカル値、スタイル値、継承値など、他の値が適用されない場合にプロパティ システムによって設定されます。 依存関係プロパティ値の実行時の割り当て時の値の優先順位の詳細については、「 依存関係プロパティの値の優先順位」を参照してください。

  • 所有者型の強制値コールバックとプロパティ変更コールバックへの参照。 publicアクセス修飾子を持つコールバック、または許可されたアクセス スコープ内にあるコールバックへの参照のみを取得できます。 依存関係プロパティのコールバックの詳細については、「 依存関係プロパティのコールバックと検証」を参照してください。

  • WPF フレームワーク レベルの依存関係プロパティの特性 (依存関係プロパティが WPF フレームワーク プロパティの場合)。 フレームワーク レイアウト エンジンやプロパティ継承ロジックなどの WPF プロセスでは、WPF フレームワーク レベルのメタデータに対してクエリを実行します。 詳細については、「 Framework プロパティのメタデータ」を参照してください。

メタデータ API

PropertyMetadata クラスは、プロパティ システムによって使用されるメタデータの大部分を格納します。 メタデータ インスタンスは、次の方法で作成および割り当てることができます。

  • 依存関係プロパティをプロパティ システムに登録する型。

  • 依存関係プロパティを定義するクラスから継承する型。

  • 依存関係プロパティの所有者として自分自身を追加する型。

型がメタデータを指定せずに依存関係プロパティを登録する場合、プロパティ システムは、その型の既定値を持つ PropertyMetadata オブジェクトを依存関係プロパティに割り当てます。

依存関係プロパティのメタデータを取得するには、GetMetadata識別子に対してDependencyPropertyオーバーロードのいずれかを呼び出します。 メタデータは、 PropertyMetadata オブジェクトとして返されます。

PropertyMetadataから派生したより具体的なメタデータ クラスは、さまざまなアーキテクチャ領域に対して存在します。 たとえば、 UIPropertyMetadata はアニメーション レポートをサポートし、 FrameworkPropertyMetadata は WPF フレームワークのプロパティをサポートします。 依存関係プロパティは、 PropertyMetadata 派生クラスに登録することもできます。 GetMetadataPropertyMetadataオブジェクトを返しますが、必要に応じて派生型にキャストして型固有のプロパティを調べることができます。

FrameworkPropertyMetadata によって公開されるプロパティ特性は、フラグと呼ばれることもあります。 FrameworkPropertyMetadata インスタンスを作成するときは、列挙型のインスタンスをFrameworkPropertyMetadataOptionsFrameworkPropertyMetadataコンストラクターに渡すことができます。 FrameworkPropertyMetadataOptions では、メタデータ フラグをビットごとの組み合わせで指定できます。 FrameworkPropertyMetadataでは、FrameworkPropertyMetadataOptionsを使用してコンストラクターシグネチャの長さを妥当な値に保ちます。 依存関係プロパティの登録時に、FrameworkPropertyMetadataOptionsに設定したメタデータ フラグは、ビットごとのフラグの組み合わせではなく、FrameworkPropertyMetadataプロパティとしてBoolean内で公開され、メタデータの特性のクエリをより直感的にします。

新しいメタデータをオーバーライドまたは作成しますか?

依存関係プロパティを継承する場合は、そのメタデータをオーバーライドして依存関係プロパティの特性を変更するオプションがあります。 ただし、メタデータをオーバーライドして依存関係プロパティのシナリオを必ずしも実現できるとは限りません。また、新しいメタデータを使用してクラスにカスタム依存関係プロパティを定義する必要がある場合もあります。 カスタム依存関係プロパティには、WPF 型で定義されている依存関係プロパティと同じ機能があります。 詳細については、「 カスタム依存関係プロパティ」を参照してください。

オーバーライドできない依存関係プロパティの特性の 1 つは、その値の型です。 継承された依存関係プロパティに必要なおおよその動作があるが、シナリオで別の値の型が必要な場合は、カスタム依存関係プロパティの実装を検討してください。 型変換やその他の実装を使用して、派生クラスのプロパティ値をリンクできる場合があります。

メタデータをオーバーライドするためのシナリオ

既存の依存関係プロパティ メタデータをオーバーライドするシナリオの例を次に示します。

  • 一般的なシナリオである既定値の変更。

  • プロパティ変更コールバックを変更または追加します。継承された依存関係プロパティが、基本実装とは異なる方法で他の依存関係プロパティと対話する場合に必要になる場合があります。 コードとマークアップの両方をサポートするプログラミング モデルの特性の 1 つは、プロパティ値が任意の順序で設定される可能性があるということです。 この要素は、プロパティ変更コールバックの実装方法に影響を与える可能性があります。 詳細については、「 依存関係プロパティのコールバックと検証」を参照してください。

  • WPF フレームワーク のプロパティ メタデータ オプションの変更。 通常、メタデータ オプションは新しい依存関係プロパティの登録中に設定されますが、 OverrideMetadata または AddOwner 呼び出しで再指定できます。 フレームワーク プロパティ メタデータのオーバーライドの詳細については、「 FrameworkPropertyMetadata の指定」を参照してください。 依存関係プロパティを登録するときにフレームワーク プロパティのメタデータ オプションを設定する方法については、「 カスタム依存関係プロパティ」を参照してください。

検証コールバックはメタデータに含まれていないため、メタデータをオーバーライドして変更することはできません。 詳細については、「 検証値のコールバック」を参照してください。

メタデータを上書き

新しい依存関係プロパティを実装する場合は、 Register メソッドのオーバーロードを使用してメタデータを設定できます。 クラスが依存関係プロパティを継承している場合は、 OverrideMetadata メソッドを使用して、継承されたメタデータ値をオーバーライドできます。 たとえば、 OverrideMetadata を使用して型固有の値を設定できます。 詳細とコード サンプルについては、「 依存関係プロパティのメタデータをオーバーライドする」を参照してください。

WPF 依存関係プロパティの例として、 Focusableがあります。 FrameworkElement クラスは、Focusableを登録します。 Control クラスは、FrameworkElementから派生し、Focusable依存関係プロパティを継承し、継承されたプロパティ メタデータをオーバーライドします。 オーバーライドにより、既定のプロパティ値が false から true に変更されますが、他の継承されたメタデータ値は保持されます。

ほとんどの既存の依存関係プロパティは仮想プロパティではないため、継承された実装によって既存のメンバーがシャドウされます。 メタデータ特性をオーバーライドすると、新しいメタデータ値によって元の値が置き換えられるか、マージされます。

  • DefaultValueの場合、新しい値によって既存の既定値が置き換えられます。 オーバーライド メタデータに DefaultValue を指定しない場合、値はメタデータで DefaultValue 指定した最も近い先祖から取得されます。

  • PropertyChangedCallbackの場合、既定のマージ ロジックでは、すべてのPropertyChangedCallback値がテーブルに格納され、すべてがプロパティの変更時に呼び出されます。 コールバックの順序は、階層の基底クラスによって登録されたコールバックが最初に実行されるクラスの深さによって決まります。

  • CoerceValueCallbackの場合、新しい値によって既存のCoerceValueCallback値が置き換えられます。 オーバーライド メタデータに CoerceValueCallback を指定しない場合、値はメタデータで CoerceValueCallback 指定した最も近い先祖から取得されます。

既定のマージ ロジックは、Merge メソッドによって実装されます。 依存関係プロパティを継承する派生クラスでカスタム マージ ロジックを指定するには、そのクラスの Merge をオーバーライドします。

所有者としてクラスを追加する

別のクラス階層に登録されている依存関係プロパティを "継承" するには、 AddOwner メソッドを使用します。 このメソッドは、通常、追加クラスが依存関係プロパティを登録した型から派生していない場合に使用されます。 AddOwner呼び出しでは、追加クラスは、継承された依存関係プロパティの型固有のメタデータを作成して割り当てることができます。 プロパティ システムの完全な参加要素にするには、コードとマークアップを使用して、追加クラスで次のパブリック メンバーを実装する必要があります。

  • 依存関係プロパティ識別子フィールド。 依存関係プロパティ識別子の値は、 AddOwner 呼び出しの戻り値です。 このフィールドは、public static readonly型のDependencyPropertyフィールドである必要があります。

  • getset アクセサーを実装する CLR ラッパー。 プロパティ ラッパーを使用すると、依存関係プロパティのコンシューマーは、他の CLR プロパティと同様に、依存関係プロパティの値を取得または設定できます。 getアクセサーとset アクセサーは、DependencyObject.GetValue呼び出しとDependencyObject.SetValue呼び出しを通じて基になるプロパティ システムと対話し、依存関係プロパティ識別子をパラメーターとして渡します。 カスタム依存関係プロパティを登録する場合と同じ方法でラッパーを実装します。 詳細については、「カスタム依存関係プロパティ」を参照してください。

AddOwnerを呼び出すクラスには、継承された依存関係プロパティのオブジェクト モデルを、新しいカスタム依存関係プロパティを定義するクラスと同じ要件があります。 詳細については、「依存関係プロパティの所有者型を追加する」を参照してください。

添付プロパティのメタデータ

WPF では、WPF 型のほとんどの UI 関連の添付プロパティが依存関係プロパティとして実装されます。 依存関係プロパティとして実装される添付プロパティは、派生クラスがオーバーライドできるメタデータなどの依存関係プロパティの概念をサポートします。 添付プロパティのメタデータは、通常、依存関係プロパティと同じになります。 オーバーライドするクラスのインスタンスで、継承された添付プロパティの既定値、プロパティ変更コールバック、WPF フレームワーク プロパティをオーバーライドできます。 詳細については、「添付プロパティのメタデータ」を参照してください。

メタデータにRegisterAttachedを指定するプロパティを登録するには、常にInheritsを使用します。 プロパティ値の継承は、アタッチされていない依存関係プロパティでは機能するように見えますが、ランタイム ツリー内の特定のオブジェクト オブジェクト分割を介した非アタッチプロパティの値の継承動作は未定義です。 Inherits プロパティは、接続されていないプロパティには関係ありません。 詳細については、「 RegisterAttached(String, Type, Type, PropertyMetadata)」および「 Inheritsの解説」セクションを参照してください。

添付プロパティの所有者としてクラスを追加する

別のクラスから添付プロパティを継承し、それをクラスのアタッチされていない依存関係プロパティとして公開するには:

  • AddOwnerを呼び出して、アタッチされた依存関係プロパティの所有者としてクラスを追加します。

  • 依存関係プロパティ識別子として使用するために、 AddOwner 呼び出しの戻り値を public static readonly フィールドに割り当てます。

  • CLR ラッパーを定義します。このラッパーは、プロパティをクラス メンバーとして追加し、アタッチされていないプロパティの使用をサポートします。

こちらも参照ください