プロパティ値の継承 (WPF .NET)
プロパティ値の継承は、Windows Presentation Foundation (WPF) プロパティ システムの機能であり、依存関係プロパティに適用されます。 プロパティ値の継承により、要素のツリー内の子要素は、最も近い親要素から特定のプロパティの値を取得できます。 親要素は、プロパティ値の継承によってプロパティ値を取得している可能性があるため、システムはページ ルートに再帰する可能性があります。
WPF プロパティ システムでは、既定ではプロパティ値の継承は有効になりません。また、依存関係プロパティ メタデータで特に有効になっていない限り、値の継承は非アクティブです。 プロパティ値の継承が有効になっている場合でも、子要素は、より高い 優先順位 値がない場合にのみプロパティ値を継承します。
前提 条件
この記事では、依存関係プロパティの基本的な知識と、依存関係プロパティの概要
要素ツリーを介した継承
プロパティ値の継承は、派生クラスが基底クラスのメンバーを継承するオブジェクト指向プログラミングのクラス継承と同じ概念ではありません。 この種の継承は WPF でもアクティブですが、XAML では、継承された基底クラスのプロパティは、派生クラスを表す XAML 要素の属性として公開されます。
プロパティ値の継承は、依存関係プロパティ値が、プロパティを含む要素のツリー内の親要素から子要素に伝達されるメカニズムです。 XAML マークアップでは、要素のツリーは入れ子になった要素として表示されます。
次の例は、XAML の入れ子になった要素を示しています。 WPF は、プロパティ値 継承 を有効にし、既定値を false
に設定するプロパティ メタデータ を使用して、UIElement クラスの AllowDrop 依存関係プロパティを登録します。 AllowDrop
依存関係プロパティは、UIElement
から派生しているため、Canvas、StackPanel、および Label 要素に存在します。 canvas1
の AllowDrop
依存関係プロパティは true
に設定されているため、子孫 stackPanel1
要素と label1
要素は AllowDrop
値として true
を継承します。
<Canvas x:Name="canvas1" Grid.Column="0" Margin="20" Background="Orange" AllowDrop="True">
<StackPanel Name="stackPanel1" Margin="20" Background="Green">
<Label Name="label1" Margin="20" Height="40" Width="40" Background="Blue"/>
</StackPanel>
</Canvas>
別の要素オブジェクトの子要素コレクションに要素オブジェクトを追加することで、プログラムによって要素のツリーを作成することもできます。 実行時に、プロパティ値の継承は結果のオブジェクト ツリーで動作します。 次の例では、stackPanel2
が canvas2
の 子コレクション に追加されます。 同様に、label2
は stackPanel2
の子コレクションに追加されます。 canvas2
の AllowDrop 依存関係プロパティは true
に設定されているため、子孫 stackPanel2
要素と label2
要素は AllowDrop
値として true
を継承します。
Canvas canvas2 = new()
{
AllowDrop = true
};
StackPanel stackPanel2 = new();
Label label2 = new();
canvas2.Children.Add(stackPanel2);
stackPanel2.Children.Add(label2);
Dim canvas2 As New Canvas With {
.AllowDrop = True
}
Dim stackPanel2 As New StackPanel()
Dim label2 As New Label()
canvas2.Children.Add(stackPanel2)
stackPanel2.Children.Add(label2)
プロパティ値の継承の実用的な応用
特定の WPF 依存関係プロパティでは、AllowDrop や FlowDirectionなど、値の継承が既定で有効になっています。 通常、値の継承が既定で有効になっているプロパティは、基本 UI 要素クラスに実装されるため、派生クラスに存在します。 たとえば、AllowDrop
は UIElement 基底クラスに実装されているため、その依存関係プロパティは、UIElement
から派生したすべてのコントロールにも存在します。 WPF を使用すると、依存関係プロパティに対する値の継承が可能になります。これは、ユーザーが親要素に対してプロパティ値を 1 回設定し、そのプロパティ値を要素ツリーの子孫要素に伝達するのに便利です。
プロパティ値の継承モデルでは、依存関係プロパティ値の優先順位に従って、継承されたプロパティ値と継承されていないプロパティ値
FlowDirection 依存関係プロパティは、親要素内のテキストおよび子 UI 要素のレイアウト方向を設定します。 通常、ページ内のテキスト要素と UI 要素のフロー方向は一貫している必要があります。
カスタム プロパティを継承可能にする
カスタム依存関係プロパティを継承可能にするには、FrameworkPropertyMetadataのインスタンスで Inherits プロパティを有効にしてから、そのメタデータ インスタンスにカスタム依存関係プロパティを登録します。 既定では、Inherits
は FrameworkPropertyMetadata
で false
に設定されます。 プロパティ値を継承可能にすることはパフォーマンスに影響するため、その機能が必要な場合にのみ Inherits
を true
に設定します。
メタデータで get
アクセサーと set
アクセサーを使用してプロパティ ラッパーを作成することもできます。 その方法で、所有者や派生型でプロパティラッパーを使用してプロパティの値を設定できます。 次の例では、IsTransparent
という名前の依存関係プロパティを作成し、Inherits
を有効にし、既定値を false
します。 この例には、get
と set
アクセサーが付いたプロパティラッパーもあります。
public class Canvas_IsTransparentInheritEnabled : Canvas
{
// Register an attached dependency property with the specified
// property name, property type, owner type, and property metadata
// (default value is 'false' and property value inheritance is enabled).
public static readonly DependencyProperty IsTransparentProperty =
DependencyProperty.RegisterAttached(
name: "IsTransparent",
propertyType: typeof(bool),
ownerType: typeof(Canvas_IsTransparentInheritEnabled),
defaultMetadata: new FrameworkPropertyMetadata(
defaultValue: false,
flags: FrameworkPropertyMetadataOptions.Inherits));
// Declare a get accessor method.
public static bool GetIsTransparent(Canvas element)
{
return (bool)element.GetValue(IsTransparentProperty);
}
// Declare a set accessor method.
public static void SetIsTransparent(Canvas element, bool value)
{
element.SetValue(IsTransparentProperty, value);
}
// For convenience, declare a property wrapper with get/set accessors.
public bool IsTransparent
{
get => (bool)GetValue(IsTransparentProperty);
set => SetValue(IsTransparentProperty, value);
}
}
Public Class Canvas_IsTransparentInheritEnabled
Inherits Canvas
' Register an attached dependency property with the specified
' property name, property type, owner type, and property metadata
' (default value is 'false' and property value inheritance is enabled).
Public Shared ReadOnly IsTransparentProperty As DependencyProperty =
DependencyProperty.RegisterAttached(
name:="IsTransparent",
propertyType:=GetType(Boolean),
ownerType:=GetType(Canvas_IsTransparentInheritEnabled),
defaultMetadata:=New FrameworkPropertyMetadata(
defaultValue:=False,
flags:=FrameworkPropertyMetadataOptions.[Inherits]))
' Declare a get accessor method.
Public Shared Function GetIsTransparent(element As Canvas) As Boolean
Return element.GetValue(IsTransparentProperty)
End Function
' Declare a set accessor method.
Public Shared Sub SetIsTransparent(element As Canvas, value As Boolean)
element.SetValue(IsTransparentProperty, value)
End Sub
' For convenience, declare a property wrapper with get/set accessors.
Public Property IsTransparent As Boolean
Get
Return GetValue(IsTransparentProperty)
End Get
Set(value As Boolean)
SetValue(IsTransparentProperty, value)
End Set
End Property
End Class
添付プロパティは概念的にはグローバル プロパティに似ています。 任意の DependencyObject で値を確認し、有効な結果を取得できます。 添付プロパティの一般的なシナリオは、子要素にプロパティ値を設定することです。そのシナリオは、該当するプロパティがツリー内の各 DependencyObject 要素に添付プロパティとして暗黙的に存在する場合に効果的です。
ツリー境界を越えてプロパティ値を継承する
プロパティの継承は、要素のツリーを走査することによって機能します。 多くの場合、このツリーは論理ツリーと並列です。 ただし、要素ツリーを定義するマークアップに、Brushなどの WPF コア レベルのオブジェクトを含めると、不連続の論理ツリーが作成されます。 論理ツリーは WPF フレームワーク レベルの概念であるため、実際の論理ツリーは概念的には Brush
を通じて拡張されません。 LogicalTreeHelper のヘルパー メソッドを使用して、論理ツリーの範囲を分析および表示できます。 プロパティ値の継承は、不連続の論理ツリーを介して継承された値を渡すことができますが、継承可能なプロパティが添付プロパティとして登録されていて、Frameなどの意図的な継承ブロック境界がない場合に限ります。
手記
プロパティ値の継承は、アタッチされていない依存関係プロパティでは機能するように見えるかもしれませんが、ランタイム ツリー内の一部の要素境界を介した非アタッチプロパティの継承動作は未定義です。 プロパティ メタデータで Inherits を指定するときは常に、RegisterAttachedを使用してプロパティを登録します。
参照
.NET Desktop feedback