如何覆寫相依性屬性 (WPF .NET) 的中繼資料
衍生自定義相依性屬性的類別時,您會繼承相依性屬性及其中繼資料。 本文說明如何藉由呼叫 OverrideMetadata 方法來覆寫已繼承相依性屬性的中繼資料。 覆寫中繼資料可讓您修改已繼承相依性屬性的特性,以符合子類別特定需求。
背景
定義相依性屬性的類別,可以在PropertyMetadata 或其中一個衍生類型中 (例如 FrameworkPropertyMetadata) 指定其特性。 其中一個特性是相依性屬性的預設值。 許多定義相依性屬性的類別,會在相依性屬性註冊期間指定屬性中繼資料。 未在註冊期間指定中繼資料時,WPF 屬性系統會指派具有預設值的 PropertyMetadata
物件。 透過類別繼承來繼承相依性屬性的衍生類別,則可以選擇覆寫任何相依性屬性的原始中繼資料。 如此一來,衍生類別就可以選擇性地修改相依性屬性特性,以符合類別需求。 呼叫 OverrideMetadata(Type, PropertyMetadata)時,衍生類別會將其類型指定為第一個參數,並將中繼資料執行個體指定為第二個參數。
若是覆寫相依性屬性中繼資料的衍生類別,則必須先指定,屬性系統才會使用該屬性。 當註冊屬性的任何類別執行個體具現化時,就會使用相依性屬性。 為了協助符合此需求,衍生類別應在其靜態建構函式中呼叫 OverrideMetadata。 將相依性屬性的中繼資料具現化之後進行覆寫,並不會引發例外狀況,但會導致屬性系統中的行為不一致。 此外,衍生類型無法覆寫相依性屬性的中繼資料超過一次,若嘗試重複覆寫,則會引發例外狀況。
範例
在下列範例中,衍生類別 TropicalAquarium
會覆寫繼承自基底類別 Aquarium
的相依性屬性中繼資料。 中繼資料類型為 FrameworkPropertyMetadata,其支援 UI 相關的 WPF 架構特性,例如 AffectsRender。 衍生類別不會覆寫繼承的 AffectsRender
旗標,但會更新衍生類別執行個體的預設值 AquariumGraphic
。
public class Aquarium : DependencyObject
{
// Register a dependency property with the specified property name,
// property type, owner type, and property metadata.
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)
);
// Declare a read-write CLR wrapper with get/set accessors.
public Uri AquariumGraphic
{
get => (Uri)GetValue(AquariumGraphicProperty);
set => SetValue(AquariumGraphicProperty, value);
}
}
Public Class Aquarium
Inherits DependencyObject
' Register a dependency property with the specified property name,
' property type, owner type, and property metadata.
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))
' Declare a read-write CLR 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
End Class
public class TropicalAquarium : Aquarium
{
// Static constructor.
static TropicalAquarium()
{
// Create a new metadata instance with a modified default value.
FrameworkPropertyMetadata newPropertyMetadata = new(
defaultValue: new Uri("http://www.contoso.com/tropical-aquarium-graphic.jpg"));
// Call OverrideMetadata on the dependency property identifier.
// Pass in the type for which the new metadata will be applied
// and the new metadata instance.
AquariumGraphicProperty.OverrideMetadata(
forType: typeof(TropicalAquarium),
typeMetadata: newPropertyMetadata);
}
}
Public Class TropicalAquarium
Inherits Aquarium
' Static constructor.
Shared Sub New()
' Create a new metadata instance with a modified default value.
Dim newPropertyMetadata As New FrameworkPropertyMetadata(
defaultValue:=New Uri("http://www.contoso.com/tropical-aquarium-graphic.jpg"))
' Call OverrideMetadata on the dependency property identifier.
' Pass in the type for which the new metadata will be applied
' and the new metadata instance.
AquariumGraphicProperty.OverrideMetadata(
forType:=GetType(TropicalAquarium),
typeMetadata:=newPropertyMetadata)
End Sub
End Class