XAML の読み込みと依存関係のプロパティ (WPF .NET)
Windows Presentation Foundation (WPF) の拡張アプリケーション マークアップ言語 (XAML) プロセッサの実装は、本質的に依存関係プロパティに対応しています。 そのため、XAML プロセッサでは、WPF プロパティ システム メソッドを使用して XAML を読み込み、依存関係プロパティ属性を処理し、GetValue や SetValueなどの WPF プロパティ システム メソッドを使用して依存関係プロパティ ラッパーを完全にバイパスします。 そのため、カスタム依存関係プロパティのプロパティ ラッパーにカスタム ロジックを追加した場合、XAML でプロパティ値が設定されている場合、XAML プロセッサによって呼び出されることはありません。
前提 条件
この記事では、依存関係プロパティの基本的な知識と、依存関係プロパティの概要
WPF XAML ローダーのパフォーマンス
WPF XAML プロセッサが依存関係プロパティのプロパティ ラッパーを使用するのではなく、SetValue を直接呼び出して依存関係プロパティの値を設定することは、計算コストが低くなります。
XAML プロセッサでプロパティ ラッパーを使用した場合は、マークアップで示されている型とメンバーのリレーションシップのみに基づいて、バッキング コードのオブジェクト モデル全体を推論する必要があります。 型は、xmlns
属性とアセンブリ属性の組み合わせを使用してマークアップから識別できますが、メンバーを識別し、属性として設定できるメンバーを決定し、サポートされているプロパティ値の型を解決するには、PropertyInfoを使用して広範なリフレクションが必要になります。
WPF プロパティ システムは、特定の DependencyObject 派生型に実装された依存関係プロパティのストレージ テーブルを保持します。 XAML プロセッサは、そのテーブルを使用して、依存関係プロパティの依存関係プロパティ識別子を推論します。 たとえば、規則により、ABC
という名前の依存関係プロパティの依存関係プロパティ識別子が ABCProperty
されます。 XAML プロセッサは、依存関係プロパティ識別子を使用して、その包含型に対して SetValue
メソッドを呼び出すことによって、依存関係プロパティの値を効率的に設定できます。
依存関係プロパティ ラッパーの詳細については、「カスタム依存関係プロパティ」を参照してください。
カスタム依存関係プロパティに対する影響
WPF XAML プロセッサは、プロパティ ラッパーをバイパスし、依存関係プロパティ値を設定するために SetValue を直接呼び出します。 そのため、カスタム依存関係プロパティの set
アクセサーに追加のロジックを配置することは避けてください。これは、XAML でプロパティ値が設定されている場合にそのロジックが実行されないためです。 set
アクセサーには、SetValue
呼び出しのみを含める必要があります。
同様に、プロパティ値を取得する WPF XAML プロセッサの側面は、プロパティ ラッパーをバイパスし、GetValueを直接呼び出します。 そのため、カスタム依存関係プロパティの get
アクセサーに追加のロジックを配置することは避けてください。これは、XAML でプロパティ値を読み取ったときにそのロジックが実行されないためです。 get
アクセサーには、GetValue
呼び出しのみを含める必要があります。
ラッパー付き依存プロパティの例
次の例は、プロパティ ラッパーを使用して推奨される依存関係プロパティ定義を示しています。 依存関係プロパティ識別子は public static readonly
フィールドとして格納され、get
アクセサーと set
アクセサーには、依存関係プロパティ値をサポートするのに必要な WPF プロパティ システムメソッドを超えるコードは含まれていません。 依存関係プロパティの値が変更されたときに実行する必要があるコードがある場合は、依存関係プロパティの PropertyChangedCallback にそのコードを配置することを検討してください。 詳細については、「
// Register a dependency property with the specified property name,
// property type, owner type, and property metadata. Store the dependency
// property identifier as a public static readonly member of the class.
public static readonly DependencyProperty AquariumGraphicProperty =
DependencyProperty.Register(
name: "AquariumGraphic",
propertyType: typeof(Uri),
ownerType: typeof(Aquarium),
typeMetadata: new FrameworkPropertyMetadata(
defaultValue: new Uri("http://www.contoso.com/aquarium-graphic.jpg"),
flags: FrameworkPropertyMetadataOptions.AffectsRender,
propertyChangedCallback: new PropertyChangedCallback(OnUriChanged))
);
// Property wrapper with get & set accessors.
public Uri AquariumGraphic
{
get => (Uri)GetValue(AquariumGraphicProperty);
set => SetValue(AquariumGraphicProperty, value);
}
// Property-changed callback.
private static void OnUriChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs e)
{
// Some custom logic that runs on effective property value change.
Uri newValue = (Uri)dependencyObject.GetValue(AquariumGraphicProperty);
Debug.WriteLine($"OnUriChanged: {newValue}");
}
' Register a dependency property with the specified property name,
' property type, owner type, and property metadata. Store the dependency
' property identifier as a public static readonly member of the class.
Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty =
DependencyProperty.Register(
name:="AquariumGraphic",
propertyType:=GetType(Uri),
ownerType:=GetType(Aquarium),
typeMetadata:=New FrameworkPropertyMetadata(
defaultValue:=New Uri("http://www.contoso.com/aquarium-graphic.jpg"),
flags:=FrameworkPropertyMetadataOptions.AffectsRender,
propertyChangedCallback:=New PropertyChangedCallback(AddressOf OnUriChanged)))
' Property wrapper with get & set accessors.
Public Property AquariumGraphic As Uri
Get
Return CType(GetValue(AquariumGraphicProperty), Uri)
End Get
Set
SetValue(AquariumGraphicProperty, Value)
End Set
End Property
' Property-changed callback.
Private Shared Sub OnUriChanged(dependencyObject As DependencyObject,
e As DependencyPropertyChangedEventArgs)
' Some custom logic that runs on effective property value change.
Dim newValue As Uri = CType(dependencyObject.GetValue(AquariumGraphicProperty), Uri)
Debug.WriteLine($"OnUriChanged: {newValue}")
End Sub
関連項目
- 依存関係プロパティの概要
- WPF における XAML
- カスタム依存関係プロパティ
- 依存関係プロパティのメタデータ
- コレクション型の依存関係プロパティ
- 依存関係プロパティのセキュリティ
- DependencyObjectsの安全なコンストラクターパターン
.NET Desktop feedback