Share via


相依性屬性中繼資料 (WPF .NET)

Windows Presentation Foundation (WPF) 屬性系統包含相依性屬性元資料包告系統。 透過元資料包告系統取得的資訊超過透過反映或一般 Common Language Runtime (CLR) 特性提供的資訊。 當您註冊相依性屬性時,您可以選擇建立和指派中繼資料給它。 如果您衍生自訂相依性屬性的類別,您可以覆寫繼承之相依性屬性的中繼資料。 而且,如果您將類別新增為相依性屬性的擁有者,您可以覆寫繼承之相依性屬性的中繼資料。

重要

.NET 7 和 .NET 6 的桌面指南檔正在建置中。

必要條件

本文假設您具備相依性屬性的基本知識,而且您已閱讀 相依性屬性概觀 。 若要遵循本文中的範例,如果您熟悉可延伸的應用程式標記語言(XAML),並知道如何撰寫 WPF 應用程式,它很有説明。

如何使用中繼資料

您可以查詢相依性屬性中繼資料,以檢查相依性屬性的特性。 當屬性系統處理相依性屬性時,它會存取其中繼資料。 相依性屬性的中繼資料物件包含下列類型的資訊:

  • 相依性屬性的預設值,在未套用其他值時由屬性系統設定,例如本機、樣式或繼承值。 如需相依性屬性值執行時間指派期間值優先順序的詳細資訊,請參閱 相依性屬性值優先順序

  • 強制值回呼和屬性在擁有者類型上變更回呼的參考。 您只能取得具有 public 存取修飾詞或在您允許存取範圍內之回呼的參考。 如需相依性屬性回呼的詳細資訊,請參閱 相依性屬性回呼和驗證

  • WPF 架構層級相依性屬性特性(如果相依性屬性是 WPF 架構屬性)。 WPF 進程,例如架構配置引擎和屬性繼承邏輯,查詢 WPF 架構層級中繼資料。 如需詳細資訊,請參閱 Framework 屬性中繼資料

中繼資料 API

類別 PropertyMetadata 會儲存屬性系統所使用的大部分中繼資料。 中繼資料實例的建立和指派方式如下:

  • 向屬性系統註冊相依性屬性的類型。

  • 繼承自訂相依性屬性之類別的類型。

  • 將自己新增為相依性屬性擁有者的類型。

如果類型註冊相依性屬性而不指定中繼資料,則屬性系統會將 PropertyMetadata 具有該類型之預設值的物件指派給相依性屬性。

若要擷取相依性屬性的 DependencyProperty 中繼資料,請在識別碼上呼叫其中 GetMetadata 一個多載。 中繼資料會以 PropertyMetadata 物件的形式傳回。

衍生自 PropertyMetadata 的更特定中繼資料類別會針對不同的架構區域而存在。 例如, UIPropertyMetadata 支援動畫報告,並支援 FrameworkPropertyMetadata WPF 架構屬性。 相依性屬性也可以向 PropertyMetadata 衍生類別註冊。 雖然 GetMetadata 會傳 PropertyMetadata 回 物件,但當適用時,您可以轉換成衍生類型來檢查類型特定的屬性。

FrameworkPropertyMetadata 公開的屬性特性有時稱為 旗標 。 當您建立 FrameworkPropertyMetadata 實例時,您可以選擇將列舉類型的 FrameworkPropertyMetadataOptions 實例傳遞至 FrameworkPropertyMetadata 建構函式。 FrameworkPropertyMetadataOptions 可讓您以位組合指定中繼資料旗標。 會 FrameworkPropertyMetadata 使用 FrameworkPropertyMetadataOptions 保持其建構函式簽章的長度合理。 在相依性屬性註冊上,您設定的 FrameworkPropertyMetadataOptions 中繼資料旗標會公開為 Boolean 屬性, FrameworkPropertyMetadata 而不是旗標的位元組合,讓查詢中繼資料特性更直覺。

覆寫或建立新的中繼資料?

當您繼承相依性屬性時,您可以選擇覆寫相依性屬性的中繼資料來變更相依性屬性的特性。 不過,您不一定能夠透過覆寫中繼資料來完成相依性屬性案例,有時必須使用新的中繼資料在類別中定義自訂相依性屬性。 自訂相依性屬性的功能與 WPF 類型所定義的相依性屬性相同。 如需詳細資訊,請參閱 自訂相依性屬性

您無法覆寫之相依性屬性的其中一個特性是其實數值型別。 如果繼承的相依性屬性具有您需要的近似行為,但您的案例需要不同的實數值型別,請考慮實作自訂相依性屬性。 您可以透過型別轉換或其他衍生類別中的實作來連結屬性值。

覆寫中繼資料的案例

覆寫現有相依性屬性中繼資料的範例案例如下:

  • 變更預設值,這是常見的案例。

  • 變更或新增屬性變更回呼,如果繼承的相依性屬性與其他相依性屬性的互動方式與其基底實作不同,則可能是必要的。 支援程式碼和標記的程式設計模型其中一個特性,就是屬性值可能依任何順序設定。 這個因素可能會影響您實作屬性變更回呼的方式。 如需詳細資訊,請參閱 相依性屬性回呼和驗證

  • 變更 WPF 架構屬性中繼資料 選項。 一般而言,中繼資料選項會在新相依性屬性的註冊期間設定,但您可以在 或 AddOwner 呼叫中 OverrideMetadata 重新指定它們。 如需覆寫架構屬性中繼資料的詳細資訊,請參閱 指定 FrameworkPropertyMetadata 。 如需如何在註冊相依性屬性時設定架構屬性中繼資料選項,請參閱 自訂相依性屬性

注意

由於驗證回呼不是中繼資料的一部分,因此無法藉由覆寫中繼資料來變更。 如需詳細資訊,請參閱 驗證值回 呼。

覆寫中繼資料

實作新的相依性屬性時,您可以使用 方法的多 Register 載來設定其中繼資料。 如果您的類別繼承相依性屬性,您可以使用 方法覆寫繼承的中繼資料值 OverrideMetadata 。 例如,您可以使用 OverrideMetadata 來設定類型特定的值。 如需詳細資訊和程式碼範例,請參閱 覆寫相依性屬性 的中繼資料。

WPF 相依性屬性的範例是 Focusable 。 類別 FrameworkElementFocusable 註冊 。 類別 Control 衍生自 FrameworkElement ,繼承 Focusable 相依性屬性,並覆寫繼承的屬性中繼資料。 覆寫會將預設屬性值從 false 變更為 true ,但會保留其他繼承的中繼資料值。

由於大部分現有的相依性屬性不是虛擬屬性,因此其繼承的實作會遮蔽現有的成員。 當您覆寫中繼資料特性時,新的中繼資料值會取代原始值或合併:

  • DefaultValue針對 ,新的值會取代現有的預設值。 如果您未在覆寫中繼資料中指定 DefaultValue ,則值會來自中繼資料中指定的最接近上階 DefaultValue

  • PropertyChangedCallback針對 ,預設合併邏輯會將所有 PropertyChangedCallback 值儲存在資料表中,而且所有值都會在屬性變更時叫用。 回呼順序取決於類別深度,其中階層中基類所註冊的回呼會先執行。

  • CoerceValueCallback針對 ,新的值將會取代現有的 CoerceValueCallback 值。 如果您未在覆寫中繼資料中指定 CoerceValueCallback ,則值會來自中繼資料中指定的最接近上階 CoerceValueCallback

注意

預設合併邏輯是由 Merge 方法實作。 您可以在繼承相依性屬性的衍生類別中指定自訂合併邏輯,方法是在該類別中覆寫 Merge

將類別新增為擁有者

若要「繼承」在不同類別階層中註冊的相依性屬性,請使用 AddOwner 方法。 當新增類別不是衍生自註冊相依性屬性的類型時,通常會使用這個方法。 在呼叫中 AddOwner ,新增類別可以建立並指派繼承相依性屬性的類型特定中繼資料。 若要成為屬性系統的完整參與者,透過程式碼和標記,新增類別應該實作這些公用成員:

  • 相依性屬性識別碼欄位。 相依性屬性識別碼的值是呼叫的 AddOwner 傳回值。 此欄位應該是 public static readonly 類型的 DependencyProperty 欄位。

  • 實作 和 set 存取子的 get CLR 包裝函式。 藉由使用屬性包裝函式,相依性屬性的取用者可以取得或設定相依性屬性值,就像任何其他 CLR 屬性一樣。 getset 存取子會透過 DependencyObject.GetValueDependencyObject.SetValue 呼叫與基礎屬性系統互動,並傳入相依性屬性識別碼做為參數。 以註冊自訂相依性屬性時的相同方式實作包裝函式。 如需詳細資訊,請參閱 自訂相依性屬性

呼叫 AddOwner 的類別,對於公開繼承之相依性屬性的物件模型,具有相同的需求,做為定義新自訂相依性屬性的類別。 如需詳細資訊,請參閱 新增相依性屬性 的擁有者類型。

附加屬性中繼資料

在 WPF 中,WPF 類型上大部分與 UI 相關的附加屬性都會實作為相依性屬性。 實作為相依性屬性的附加屬性支援相依性屬性概念,例如衍生類別可以覆寫的中繼資料。 附加屬性的中繼資料通常與相依性屬性不同。 您可以在覆寫類別的實例上覆寫繼承附加屬性的預設值、屬性變更回呼和 WPF 架構屬性。 如需詳細資訊,請參閱 附加屬性中繼資料

注意

一律使用 RegisterAttached 來註冊您在 Inherits 中繼資料中指定的屬性。 雖然屬性值繼承可能適用于非附加的相依性屬性,但未定義執行時間樹狀結構中特定物件物件分割之非附加屬性的值繼承行為。 屬性 Inherits 與未附加的屬性無關。 如需詳細資訊,請參閱 RegisterAttached(String, Type, Type, PropertyMetadata) 的 和 備註一節 Inherits

將類別新增為附加屬性的擁有者

若要從另一個類別繼承附加屬性,但將其公開為類別上的非附加相依性屬性:

  • 呼叫 AddOwner 以將類別新增為附加相依性屬性的擁有者。

  • 將呼叫的 AddOwner 傳回值指派給 public static readonly 欄位,以做為相依性屬性識別碼。

  • 定義 CLR 包裝函式,此包裝函式會將 屬性新增為類別成員,並支援非附加的屬性使用方式。

另請參閱