相依性屬性中繼資料 (WPF .NET)
Windows Presentation Foundation (WPF) 屬性系統包含相依性屬性中繼資料報告系統。 透過中繼資料報告系統提供的資訊超過透過反射或一般通用語言執行平台 (CLR) 特性提供的資訊。 當您註冊相依性屬性時,您可以選擇為它建立中繼資料並將該中繼資料指派給它。 若衍生自定義相依性屬性的類別,您可以覆寫繼承相依性屬性的中繼資料。 而且,若新增類別作為相依性屬性的擁有者,您可以覆寫繼承相依性屬性的中繼資料。
必要條件
本文假設您具備相依性屬性的基本知識,而且已閱讀相依性屬性概觀。 若要遵循本文中的範例,建議您先熟悉 Extensible Application Markup Language (XAML),並了解如何撰寫 WPF 應用程式。
如何使用中繼資料
您可以查詢相依性屬性中繼資料,檢查相依性屬性的特性。 當屬性系統處理相依性屬性時,會存取其中繼資料。 相依性屬性的中繼資料物件包含下列類型的資訊:
相依性屬性的預設值 (未套用任何其他值時由屬性系統設定),例如本機、樣式或繼承值。 如需相依性屬性值執行階段指派期間值優先順序的詳細資訊,請參閱相依性屬性值優先順序。
強制型轉值回呼的參考,以及擁有者類型中屬性變更回呼的參考。 您只能取得具有
public
存取修飾元或在您允許存取範圍內之回呼的參考。 如需相依性屬性回呼的詳細資訊,請參閱相依性屬性回呼和驗證。WPF 架構層級相依性屬性特性 (如果相依性屬性是 WPF 架構屬性)。 WPF 處理 (例如架構配置引擎和屬性繼承邏輯) 會查詢 WPF 架構層級中繼資料。 如需詳細資訊,請參閱架構屬性中繼資料。
中繼資料 API
PropertyMetadata 類別會儲存屬性系統所使用的大部分中繼資料。 中繼資料執行個體可以依照下列條件建立和指派:
向屬性系統註冊相依性屬性的類型。
繼承自定義相依性屬性之類別的類型。
自行新增為相依性屬性擁有者的類型。
如果類型註冊相依性屬性而未指定中繼資料,則屬性系統會將具有該類型預設值的 PropertyMetadata
物件指派給相依性屬性。
若要擷取相依性屬性的中繼資料,請對 GetMetadata 識別碼呼叫其中一個 DependencyProperty 多載。 中繼資料會以 PropertyMetadata
物件的形式傳回。
在不同的架構區域存在更多衍生自 PropertyMetadata
的特定中繼資料類別。 例如,UIPropertyMetadata 支援動畫報告,而 FrameworkPropertyMetadata 支援 WPF 架構屬性。 相依性屬性也可以註冊 PropertyMetadata
衍生類別。 雖然 GetMetadata
會傳回 PropertyMetadata
物件,但您可以在適當時轉換成衍生類型,以檢查類型特有的屬性。
FrameworkPropertyMetadata
所公開的屬性特性有時稱為旗標。 您建立 FrameworkPropertyMetadata
執行個體時,您可以選擇將列舉類型 FrameworkPropertyMetadataOptions 的執行個體傳遞至 FrameworkPropertyMetadata
建構函式。
FrameworkPropertyMetadataOptions
可讓您以位元組合的方式指定中繼資料旗標。
FrameworkPropertyMetadata
使用 FrameworkPropertyMetadataOptions
來保持合理的建構函式簽章長度。 在相依性屬性註冊時,您在 FrameworkPropertyMetadataOptions
中設定的中繼資料旗標會在 FrameworkPropertyMetadata
中公開為 Boolean
屬性,而不是旗標的位元組合,以更直覺的方式查詢中繼資料特性。
覆寫或建立新的中繼資料?
當您繼承相依性屬性時,您可以選擇覆寫相依性屬性的中繼資料來變更其特性。 不過,您不一定能夠透過覆寫中繼資料來完成相依性屬性案例,有時必須使用新的中繼資料在類別中定義自訂相依性屬性。 自訂相依性屬性的功能與 WPF 類型所定義的相依性屬性相同。 如需詳細資訊,請參閱自訂相依性屬性。
您無法覆寫的相依性屬性特性為實值型別。 如果繼承的相依性屬性具有您所需要的近似行為,但您的案例需要不同的實值型別,請考慮實作自訂相依性屬性。 您可以透過型別轉換或其他衍生類別中的實作來連結屬性值。
覆寫中繼資料的案例
覆寫現有相依性屬性中繼資料的範例案例如下:
變更預設值,這是常見的案例。
變更或新增屬性變更回呼,如果繼承的相依性屬性與其他相依性屬性的互動方式與其基礎實作不同,則可能有此必要。 支援程式碼和標記的程式設計模型特性之一,就是屬性值可按照任何順序設定。 這個因素會影響您實作屬性變更回呼的方式。 如需詳細資訊,請參閱相依性屬性回呼和驗證。
變更 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 欄位。實作
get
和set
存取子的 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 包裝函式,此包裝函式可以將屬性新增為類別成員,並支援非附加的屬性使用方式。