自訂相依性屬性Custom Dependency Properties

本主題會說明 Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) 應用程式開發人員和元件作者可能想要建立自訂相依性屬性的原因,並說明實作步驟以及某些可以改善屬性的效能、可用性或多功能的實作選項。This topic describes the reasons that Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) application developers and component authors might want to create custom dependency property, and describes the implementation steps as well as some implementation options that can improve performance, usability, or versatility of the property.

PrerequisitesPrerequisites

本主題假設您已從 WPFWPF 類別的現有相依性屬性消費者角度了解相依性屬性,並已閱讀相依性屬性概觀主題。This topic assumes that you understand dependency properties from the perspective of a consumer of existing dependency properties on WPFWPF classes, and have read the Dependency Properties Overview topic. 為遵循本主題中的範例,您也應該了解 Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML) 並知道如何撰寫 WPFWPF 應用程式。In order to follow the examples in this topic, you should also understand Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML) and know how to write WPFWPF applications.

什麼是相依性屬性?What Is a Dependency Property?

您可以藉由將它實作為相依性屬性,來啟用其他 (CLR) 屬性的通用語言執行平臺,以支援樣式、資料系結、繼承、動畫和預設值。You can enable what would otherwise be a common language runtime (CLR) property to support styling, data binding, inheritance, animations, and default values by implementing it as a dependency property. 相依性屬性是透過 WPFWPF 呼叫 Register (或 RegisterReadOnly) 方法,以及由識別碼欄位所支援的方法,向屬性系統註冊的屬性 DependencyPropertyDependency properties are properties that are registered with the WPFWPF property system by calling the Register method (or RegisterReadOnly), and that are backed by a DependencyProperty identifier field. 相依性屬性只能由型別使用 DependencyObject ,但 DependencyObject 在類別階層中相當高 WPFWPF ,因此大部分的可用類別 WPFWPF 都可支援相依性屬性。Dependency properties can be used only by DependencyObject types, but DependencyObject is quite high in the WPFWPF class hierarchy, so the majority of classes available in WPFWPF can support dependency properties. 如需相依性屬性的詳細資訊,以及在此 SDK 中用來描述這些屬性的部分術語和慣例,請參閱相依性 屬性總覽For more information about dependency properties and some of the terminology and conventions used for describing them in this SDK, see Dependency Properties Overview.

相依性屬性範例Examples of Dependency Properties

在類別上實作為相依性屬性的範例 WPFWPF 包括 Background 屬性、 Width 屬性和屬性(property),還有 Text 其他許多專案。Examples of dependency properties that are implemented on WPFWPF classes include the Background property, the Width property, and the Text property, among many others. 類別所公開的每個相依性屬性都有一個 DependencyProperty 在相同類別上公開之類型的對應公用靜態欄位。Each dependency property exposed by a class has a corresponding public static field of type DependencyProperty exposed on that same class. 這是相依性屬性的識別碼。This is the identifier for the dependency property. 識別碼依慣例命名︰相依性屬性的名稱後綴字串 PropertyThe identifier is named using a convention: the name of the dependency property with the string Property appended to it. 例如,屬性的對應 DependencyProperty 識別碼欄位 BackgroundBackgroundPropertyFor example, the corresponding DependencyProperty identifier field for the Background property is BackgroundProperty. 識別碼會儲存所註冊之相依性屬性的相關資訊,然後稍後再針對涉及相依性屬性的其他作業(例如呼叫)使用該識別碼 SetValueThe identifier stores the information about the dependency property as it was registered, and the identifier is then used later for other operations involving the dependency property, such as calling SetValue.

如相依性 屬性總覽中所述, WPFWPF 除了大多數附加屬性) 之外, (中的所有相依性屬性也是因為「包裝函式」的實作為 CLR 屬性。As mentioned in the Dependency Properties Overview, all dependency properties in WPFWPF (except most attached properties) are also CLR properties because of the "wrapper" implementation. 因此,您可以從程式碼取得或設定相依性屬性,方法是呼叫以您使用其他 CLR 屬性的相同方式來定義包裝函式的 CLR 存取子。Therefore, from code, you can get or set dependency properties by calling CLR accessors that define the wrappers in the same manner that you would use other CLR properties. 作為已建立相依性屬性的取用者,您通常不會使用 DependencyObject 方法 GetValue 和,也就 SetValue 是基礎屬性系統的連接點。As a consumer of established dependency properties, you do not typically use the DependencyObject methods GetValue and SetValue, which are the connection point to the underlying property system. 相反地,CLR 屬性的現有執行會在 GetValue SetValue 屬性的和包裝函式 getset ,適當地使用識別碼欄位來呼叫。Rather, the existing implementation of the CLR properties will have already called GetValue and SetValue within the get and set wrapper implementations of the property, using the identifier field appropriately. 如果您要自行實作自訂的相依性屬性,則會以類似的方式定義包裝函式。If you are implementing a custom dependency property yourself, then you will be defining the wrapper in a similar way.

您應於何時實作相依性屬性?When Should You Implement a Dependency Property?

當您在類別上執行屬性時,只要您的類別衍生自 DependencyObject ,您就可以選擇使用識別碼來備份您的屬性, DependencyProperty 因此將其設為相依性屬性。When you implement a property on a class, so long as your class derives from DependencyObject, you have the option to back your property with a DependencyProperty identifier and thus to make it a dependency property. 讓您的屬性成為相依性屬性並非絕對必要或合適,視案例需求而定。Having your property be a dependency property is not always necessary or appropriate, and will depend on your scenario needs. 有時候,支援有私用欄位的屬性,一般的技巧即已足夠。Sometimes, the typical technique of backing your property with a private field is adequate. 但只要您希望屬性支援下列一或多項 WPFWPF 功能,就應該將屬性實作為相依性屬性:However, you should implement your property as a dependency property whenever you want your property to support one or more of the following WPFWPF capabilities:

  • 您希望屬性在樣式中是可設定的。You want your property to be settable in a style. 如需詳細資訊,請參閱設定 樣式和範本For more information, see Styling and Templating.

  • 您希望屬性支援資料繫結。You want your property to support data binding. 如需資料繫結相依性屬性的詳細資訊,請參閱繫結兩個控制項的屬性For more information about data binding dependency properties, see Bind the Properties of Two Controls.

  • 您希望屬性可使用動態資源參考來設定。You want your property to be settable with a dynamic resource reference. 如需詳細資訊,請參閱 XAML 資源For more information, see XAML Resources.

  • 您想要自動繼承項目樹狀結構父項目的屬性值。You want to inherit a property value automatically from a parent element in the element tree. 在此情況下, RegisterAttached 即使您也建立了 CLR 存取的屬性包裝函式,也會向方法註冊。In this case, register with the RegisterAttached method, even if you also create a property wrapper for CLR access. 如需詳細資訊,請參閱屬性值繼承For more information, see Property Value Inheritance.

  • 您希望屬性可製成動畫。You want your property to be animatable. 如需詳細資訊,請參閱 動畫總覽For more information, see Animation Overview.

  • 當屬性系統、環境或使用者所採取的動作,或讀取和使用樣式變更了先前的屬性值時,您希望屬性系統能夠回報。You want the property system to report when the previous value of the property has been changed by actions taken by the property system, the environment, or the user, or by reading and using styles. 使用屬性中繼資料,您的屬性可以指定每次屬性系統判定屬性值變更時都會叫用回呼方法。By using property metadata, your property can specify a callback method that will be invoked each time the property system determines that your property value was definitively changed. 相關的概念是屬性值強制型轉。A related concept is property value coercion. 如需詳細資訊,請參閱相依性屬性回呼和驗證For more information, see Dependency Property Callbacks and Validation.

  • 您想要使用 WPFWPF 程序也使用的已建立中繼資料慣例,例如報告變更屬性值是否應該需要配置系統重新撰寫項目的視覺效果。You want to use established metadata conventions that are also used by WPFWPF processes, such as reporting whether changing a property value should require the layout system to recompose the visuals for an element. 或者您想要能夠使用中繼資料覆寫,以便衍生類別可以變更中繼資料型的特性,例如預設值。Or you want to be able to use metadata overrides so that derived classes can change metadata-based characteristics such as the default value.

  • 您希望自訂控制項的屬性接收 Visual Studio WPF 設計工具支援,例如 屬性 視窗編輯。You want properties of a custom control to receive Visual Studio WPF Designer support, such as Properties window editing. 如需詳細資訊,請參閱控制項撰寫概觀For more information, see Control Authoring Overview.

當您檢查這些案例時,您也應該考慮是否能夠以覆寫現有相依性屬性中繼資料的方式完成您的案例,而不是實作全新的屬性。When you examine these scenarios, you should also consider whether you can achieve your scenario by overriding the metadata of an existing dependency property, rather than implementing a completely new property. 中繼資料覆寫是否實際可行,取決於您的案例,以及該案例與現有 WPFWPF 相依性屬性和類別實作的類似程度。Whether a metadata override is practical depends on your scenario and how closely that scenario resembles the implementation in existing WPFWPF dependency properties and classes. 如需覆寫現有屬性中繼資料的詳細資訊,請參閱相依性屬性中繼資料For more information about overriding metadata on existing properties, see Dependency Property Metadata.

定義相依性屬性所使用的檢查清單Checklist for Defining a Dependency Property

定義相依性屬性包含四個不同的概念。Defining a dependency property consists of four distinct concepts. 這些概念不一定得是嚴苛的程序步驟,因為其中有些最後會結合為實作中的單一段程式碼︰These concepts are not necessarily strict procedural steps, because some of these end up being combined as single lines of code in the implementation:

  • (選擇性) 建立相依性屬性的屬性中繼資料。(Optional) Create property metadata for the dependency property.

  • 向屬性系統登錄屬性名稱,指定擁有者類型和屬性值類型。Register the property name with the property system, specifying an owner type and the type of the property value. 如經使用,也指定屬性中繼資料。Also specify the property metadata, if used.

  • DependencyProperty將識別碼定義為 public static readonly 擁有者類型上的欄位。Define a DependencyProperty identifier as a public static readonly field on the owner type.

  • 定義其名稱符合相依性屬性名稱的 CLR 「包裝函式」屬性。Define a CLR "wrapper" property whose name matches the name of the dependency property. 執行 CLR 「包裝函式」屬性的 get 和存取子, set 以連接到支援它的相依性屬性。Implement the CLR "wrapper" property's get and set accessors to connect with the dependency property that backs it.

向屬性系統登錄屬性Registering the Property with the Property System

為使屬性成為相依性屬性,您必須將該屬性登錄到屬性系統維護的資料表中,並給它唯一識別碼用為後續屬性系統作業的限定詞。In order for your property to be a dependency property, you must register that property into a table maintained by the property system, and give it a unique identifier that is used as the qualifier for later property system operations. 這些作業可能是內部作業,或是您自己的程式碼呼叫屬性系統 Api。These operations might be internal operations, or your own code calling property system APIs. 若要註冊屬性,您可以在類別內 (類別內的 Register 方法,但是在) 的成員定義以外的任何成員定義中呼叫方法。To register the property, you call the Register method within the body of your class (inside the class, but outside of any member definitions). 方法呼叫也會提供識別碼欄位 Register 作為傳回值。The identifier field is also provided by the Register method call, as the return value. Register呼叫是在其他成員定義以外完成的原因,是因為您使用這個傳回值來指派型別的欄位,並將其建立 public static readonly DependencyProperty 為類別的一部分。The reason that the Register call is done outside of other member definitions is because you use this return value to assign and create a public static readonly field of type DependencyProperty as part of your class. 此欄位會變成您相依性屬性的識別碼。This field becomes the identifier for your dependency property.

public static readonly DependencyProperty AquariumGraphicProperty = DependencyProperty.Register(
  "AquariumGraphic",
  typeof(Uri),
  typeof(AquariumObject),
  new FrameworkPropertyMetadata(null,
      FrameworkPropertyMetadataOptions.AffectsRender,
      new PropertyChangedCallback(OnUriChanged)
  )
);
Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty = DependencyProperty.Register("AquariumGraphic", GetType(Uri), GetType(AquariumObject), New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.AffectsRender, New PropertyChangedCallback(AddressOf OnUriChanged)))

相依性屬性命名慣例Dependency Property Name Conventions

相依性屬性有已建立的命名慣例,除非例外情況,否則必須遵循。There are established naming conventions regarding dependency properties that you must follow in all but exceptional circumstances.

相依性屬性本身會有基本名稱 "AquariumGraphic",如同在此範例中,它會指定為的第一個參數 RegisterThe dependency property itself will have a basic name, "AquariumGraphic" as in this example, which is given as the first parameter of Register. 該名稱在每個登錄類型中都必須是唯一的。That name must be unique within each registering type. 透過基底類型繼承的相依性屬性視為登錄類型的一部分,已繼承屬性的名稱無法再次登錄。Dependency properties inherited through base types are considered to be already part of the registering type; names of inherited properties cannot be registered again. 不過,即使不能繼承該相依性屬性,還有一種技巧可將類別新增為相依性屬性的擁有者;如需詳細資訊,請參閱相依性屬性中繼資料However, there is a technique for adding a class as owner of a dependency property even when that dependency property is not inherited; for details, see Dependency Property Metadata.

當您建立識別碼欄位時,請以登錄屬性時所用名稱命名此欄位,再加上尾碼 PropertyWhen you create the identifier field, name this field by the name of the property as you registered it, plus the suffix Property. 此欄位是相依性屬性的識別碼,稍後將用來做為的輸入, SetValue 以及透過您自己的程式碼,由任何其他程式碼存取屬性(由您允許的任何外部程式碼存取)、 GetValue 屬性系統所允許的任何外部程式碼存取,以及可能的 XAMLXAML 處理器。This field is your identifier for the dependency property, and it will be used later as an input for the SetValue and GetValue calls you will make in the wrappers, by any other code access to the property by your own code, by any external code access you allow, by the property system, and potentially by XAMLXAML processors.

注意

在類別主體中定義相依性屬性是一般的實作,但也可能在類別靜態建構函式中定義相依性屬性。Defining the dependency property in the class body is the typical implementation, but it is also possible to define a dependency property in the class static constructor. 如果您需要多行程式碼來初始化相依性屬性,這個方式可能有意義。This approach might make sense if you need more than one line of code to initialize the dependency property.

實作 "wrapper"Implementing the "Wrapper"

您的包裝函式實作為在執行中的呼叫 GetValue get ,而 SetValueset 執行 (原始註冊呼叫和欄位也會顯示在此處,以清楚) 。Your wrapper implementation should call GetValue in the get implementation, and SetValue in the set implementation (the original registration call and field are shown here too for clarity).

在所有但例外的情況下,您的包裝函式的執行應該 GetValue 分別執行和 SetValue 動作。In all but exceptional circumstances, your wrapper implementations should perform only the GetValue and SetValue actions, respectively. 相關原因討論請參閱 XAML 載入和相依性屬性主題。The reason for this is discussed in the topic XAML Loading and Dependency Properties.

WPFWPF 類別中提供的所有現有公用相依性屬性都使用這個簡單的包裝函式實作模型,相依性屬性運作方式最複雜的部分或為固有的屬性系統行為,或為透過其他概念予以實行,例如透過屬性中繼資料的強制型轉或屬性變更回呼。All existing public dependency properties that are provided on the WPFWPF classes use this simple wrapper implementation model; most of the complexity of how dependency properties work is either inherently a behavior of the property system, or is implemented through other concepts such as coercion or property change callbacks through property metadata.


public static readonly DependencyProperty AquariumGraphicProperty = DependencyProperty.Register(
  "AquariumGraphic",
  typeof(Uri),
  typeof(AquariumObject),
  new FrameworkPropertyMetadata(null,
      FrameworkPropertyMetadataOptions.AffectsRender,
      new PropertyChangedCallback(OnUriChanged)
  )
);
public Uri AquariumGraphic
{
  get { return (Uri)GetValue(AquariumGraphicProperty); }
  set { SetValue(AquariumGraphicProperty, value); }
}

Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty = DependencyProperty.Register("AquariumGraphic", GetType(Uri), GetType(AquariumObject), New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.AffectsRender, New PropertyChangedCallback(AddressOf OnUriChanged)))
Public Property AquariumGraphic() As Uri
    Get
        Return CType(GetValue(AquariumGraphicProperty), Uri)
    End Get
    Set(ByVal value As Uri)
        SetValue(AquariumGraphicProperty, value)
    End Set
End Property

同樣地,依照慣例,包裝函式屬性的名稱必須與所選擇的名稱相同,並指定為註冊屬性之呼叫的第一個參數 RegisterAgain, by convention, the name of the wrapper property must be the same as the name chosen and given as first parameter of the Register call that registered the property. 如果您的屬性不遵循慣例,不一定會停用所有可能的用途,但您會遇到幾個值得注意的問題︰If your property does not follow the convention, this does not necessarily disable all possible uses, but you will encounter several notable issues:

  • 樣式和範本的某些方面不起作用。Certain aspects of styles and templates will not work.

  • 大部分的工具和設計工具必須依賴命名慣例,才能正確序列化 XAMLXAML,或依屬性層級提供設計工具環境協助。Most tools and designers must rely on the naming conventions to properly serialize XAMLXAML, or to provide designer environment assistance at a per-property level.

  • 目前的載入器執行會 WPFWPF XAMLXAML 完全略過包裝函式,並在處理屬性值時依賴命名慣例。The current implementation of the WPFWPF XAMLXAML loader bypasses the wrappers entirely, and relies on the naming convention when processing attribute values. 如需詳細資訊,請參閱 XAML 相依性屬性For more information, see XAML Loading and Dependency Properties.

新相依性屬性的屬性中繼資料Property Metadata for a New Dependency Property

當您登錄相依性屬性時,登錄會透過屬性系統建立儲存屬性特性的中繼資料物件。When you register a dependency property, the registration through the property system creates a metadata object that stores property characteristics. 其中有許多特性都有預設值,如果屬性是以的簡單簽章註冊,就會設定這些預設值 RegisterMany of these characteristics have defaults that are set if the property is registered with the simple signatures of Register. 的其他簽章可 Register 讓您指定要在註冊屬性時所需的中繼資料。Other signatures of Register allow you to specify the metadata that you want as you register the property. 相依性屬性最常指定的中繼資料,是套用在新執行個體的預設值,而新執行個體使用該屬性。The most common metadata given for dependency properties is to give them a default value that is applied on new instances that use the property.

如果您要建立存在於衍生類別的相依性屬性 FrameworkElement ,您可以使用更特殊化的中繼資料類別, FrameworkPropertyMetadata 而不是基類 PropertyMetadataIf you are creating a dependency property that exists on a derived class of FrameworkElement, you can use the more specialized metadata class FrameworkPropertyMetadata rather than the base PropertyMetadata class. 類別的函式 FrameworkPropertyMetadata 有數個簽章,您可以在其中指定各種中繼資料特性的組合。The constructor for the FrameworkPropertyMetadata class has several signatures where you can specify various metadata characteristics in combination. 如果您只想要指定預設值,請使用採用型別之單一參數的簽章 ObjectIf you want to specify the default value only, use the signature that takes a single parameter of type Object. 傳遞該物件參數做為屬性的特定類型預設值 (所提供的預設值必須是您在 propertyType 呼叫) 中提供作為參數的型別 RegisterPass that object parameter as a type-specific default value for your property (the default value provided must be the type you provided as the propertyType parameter in the Register call).

針對 FrameworkPropertyMetadata ,您也可以指定屬性的中繼資料選項旗標。For FrameworkPropertyMetadata, you can also specify metadata option flags for your property. 這些旗標在登錄後會轉換成屬性中繼資料中的個別屬性,用以與版面配置引擎等其他處理序溝通特定條件。These flags are converted into discrete properties on the property metadata after registration and are used to communicate certain conditionals to other processes such as the layout engine.

設定適當的中繼資料旗標Setting Appropriate Metadata Flags

  • 如果您的屬性 (或其值的變更) 會影響 使用者介面 (UI)user interface (UI) ,且特別影響版面配置系統應該如何調整或轉譯頁面中的元素,請設定下列其中一個或多個旗標: AffectsMeasureAffectsArrangeAffectsRenderIf your property (or changes in its value) affects the 使用者介面 (UI)user interface (UI), and in particular affects how the layout system should size or render your element in a page, set one or more of the following flags: AffectsMeasure, AffectsArrange, AffectsRender.

    • AffectsMeasure 指出這個屬性的變更需要變更以轉譯, UIUI 其中包含物件可能需要更多或更少的父系空間。AffectsMeasure indicates that a change to this property requires a change to UIUI rendering where the containing object might require more or less space within the parent. 例如,"Width" 屬性應該設定此旗標。For example, a "Width" property should have this flag set.

    • AffectsArrange 指出這個屬性的變更需要變更, UIUI 通常不需要在專用空間中變更,但卻指出空間內的位置已變更。AffectsArrange indicates that a change to this property requires a change to UIUI rendering that typically does not require a change in the dedicated space, but does indicate that the positioning within the space has changed. 例如,"Alignment" 屬性應該設定此旗標。For example, an "Alignment" property should have this flag set.

    • AffectsRender 表示已發生一些其他變更,而不會影響版面配置和量值,但需要另一個轉譯。AffectsRender indicates that some other change has occurred that will not affect layout and measure, but does require another render. 例如可變更現有項目色彩的 "Background" 等屬性。An example would be a property that changes a color of an existing element, such as "Background".

    • 這些旗標在您自己的屬性系統或配置回呼覆寫實作中,通常用為中繼資料的通訊協定。These flags are often used as a protocol in metadata for your own override implementations of property system or layout callbacks. 比方說, OnPropertyChanged InvalidateArrange 如果實例的任何屬性報告值變更,而 AffectsArrange true 其中繼資料中有任何屬性,您可能會有回呼呼叫。For instance, you might have an OnPropertyChanged callback that will call InvalidateArrange if any property of the instance reports a value change and has AffectsArrange as true in its metadata.

  • 某些屬性會影響包含父項目的轉譯特性,超過前文所述之所需大小的變更。Some properties may affect the rendering characteristics of the containing parent element, in ways above and beyond the changes in required size mentioned above. 例如,在非固定格式 MinOrphanLines 檔模型中使用的屬性,其中該屬性的變更可能會變更包含段落之 flow 檔的整體轉譯。An example is the MinOrphanLines property used in the flow document model, where changes to that property can change the overall rendering of the flow document that contains the paragraph. 使用 AffectsParentArrangeAffectsParentMeasure 來識別您自己的屬性中的類似案例。Use AffectsParentArrange or AffectsParentMeasure to identify similar cases in your own properties.

  • 相依性屬性預設支援資料繫結。By default, dependency properties support data binding. 對於沒有任何實際案例可進行資料繫結的情況,或者大型物件的資料繫結效能認定有問題的情況,您可以故意停用資料繫結。You can deliberately disable data binding, for cases where there is no realistic scenario for data binding, or where performance in data binding for a large object is recognized as a problem.

  • 依預設,相依性屬性的資料系結預設 ModeOneWayBy default, data binding Mode for dependency properties defaults to OneWay. 您一律可以將系結變更為 TwoWay 每個系結實例。如需詳細資料,請參閱 指定系結的方向。You can always change the binding to be TwoWay per binding instance; for details, see Specify the Direction of the Binding. 但是,如果您是相依性屬性作者,則可以選擇讓屬性 TwoWay 依預設使用系結模式。But as the dependency property author, you can choose to make the property use TwoWay binding mode by default. 現有相依性屬性的範例為 MenuItem.IsSubmenuOpen ; 這個屬性的情節是 IsSubmenuOpen 設定邏輯和 MenuItem 與預設主題樣式互動的組合。An example of an existing dependency property is MenuItem.IsSubmenuOpen; the scenario for this property is that the IsSubmenuOpen setting logic and the compositing of MenuItem interact with the default theme style. 屬性邏輯會以原生 IsSubmenuOpen 方式使用資料系結,根據其他狀態屬性和方法呼叫來維護屬性的狀態。The IsSubmenuOpen property logic uses data binding natively to maintain the state of the property in accordance to other state properties and method calls. 預設系結的另一個範例屬性 TwoWayTextBox.TextAnother example property that binds TwoWay by default is TextBox.Text.

  • 您也可以藉由設定旗標,在自訂相依性屬性中啟用屬性繼承 InheritsYou can also enable property inheritance in a custom dependency property by setting the Inherits flag. 屬性繼承對父項目和子項目有共同屬性的案例很有用,而且對子項目將特定屬性值設定為和父項目設定的值一樣,才有意義。Property inheritance is useful for a scenario where parent elements and child elements have a property in common, and it makes sense for the child elements to have that particular property value set to the same value as the parent set it. 可繼承的屬性是範例可用於系結 DataContext 作業,以啟用資料呈現的重要主從階層案例。An example inheritable property is DataContext, which is used for binding operations to enable the important master-detail scenario for data presentation. 藉由建立 DataContext 可繼承的專案,任何子項目也會繼承該資料內容。By making DataContext inheritable, any child elements inherit that data context also. 因為屬性值繼承的緣故,您可以指定位在網頁或應用程式根目錄中的資料內容,不需要重新指定即可繫結所有可能的子項目。Because of property value inheritance, you can specify a data context at the page or application root, and do not need to respecify it for bindings in all possible child elements. DataContext 這也是一個很好的範例,說明繼承會覆寫預設值,但永遠可以在本機設定任何特定的子專案;如需詳細資訊,請參閱 使用 Master-Detail 模式與階層式資料DataContext is also a good example to illustrate that inheritance overrides the default value, but it can always be set locally on any particular child element; for details, see Use the Master-Detail Pattern with Hierarchical Data. 屬性值繼承確實有可能的效能成本,因此應謹慎使用。如需詳細資訊,請參閱屬性值繼承Property value inheritance does have a possible performance cost, and thus should be used sparingly; for details, see Property Value Inheritance.

  • 設定 Journal 旗標,以指出流覽日誌服務是否應該偵測或使用您的相依性屬性。Set the Journal flag to indicate if your dependency property should be detected or used by navigation journaling services. 其中一個範例是 SelectedIndex 屬性; 在選取控制項中選取的任何專案,都應該在流覽日誌記錄時保存。An example is the SelectedIndex property; any item selected in a selection control should be persisted when the journaling history is navigated.

唯讀相依性屬性Read-Only Dependency Properties

您可以定義唯讀的相依性屬性。You can define a dependency property that is read-only. 但您為何可能將屬性定義為唯讀的案例有點不同,和向屬性系統登錄它們並公開識別碼的程序一樣。However, the scenarios for why you might define your property as read-only are somewhat different, as is the procedure for registering them with the property system and exposing the identifier. 如需詳細資訊,請參閱唯讀相依性屬性For more information, see Read-Only Dependency Properties.

集合類型相依性屬性Collection-Type Dependency Properties

集合類型相依性屬性要考慮一些其他的實作問題。Collection-type dependency properties have some additional implementation issues to consider. 如需詳細資訊,請參閱集合類型相依性屬性For details, see Collection-Type Dependency Properties.

相依性屬性安全性考量Dependency Property Security Considerations

相依性屬性應該宣告為公用屬性。Dependency properties should be declared as public properties. 相依性屬性識別碼欄位應該宣告為公用靜態欄位。Dependency property identifier fields should be declared as public static fields. 即使您嘗試宣告其他存取層級 (例如受保護的) ,還是可以透過識別碼搭配屬性系統 Api 來存取相依性屬性。Even if you attempt to declare other access levels (such as protected), a dependency property can always be accessed through the identifier in combination with the property system APIs. 即使是屬於屬性系統一部分的元資料包告或值判斷 Api (例如),也可能會有受保護的識別碼欄位 LocalValueEnumeratorEven a protected identifier field is potentially accessible because of metadata reporting or value determination APIs that are part of the property system, such as LocalValueEnumerator. 如需詳細資訊,請參閱相依性屬性的安全性For more information, see Dependency Property Security.

相依性屬性和類別建構函式Dependency Properties and Class Constructors

Managed 程式碼程式設計中有項一般原則 (通常由 FxCop 等程式碼分析工具強制執行),類別建構函式不應該呼叫虛擬方法。There is a general principle in managed code programming (often enforced by code analysis tools such as FxCop) that class constructors should not call virtual methods. 這是因為建構函式可以呼叫為衍生類別建構函式的基底初始化,而透過建構函式進入虛擬方法,可能會發生在建構中的物件執行個體尚未完全初始化的狀態。This is because constructors can be called as base initialization of a derived class constructor, and entering the virtual method through the constructor might occur at an incomplete initialization state of the object instance being constructed. 當您衍生自任何已衍生自的類別時 DependencyObject ,您應該注意到屬性系統本身會在內部呼叫和公開虛擬方法。When you derive from any class that already derives from DependencyObject, you should be aware that the property system itself calls and exposes virtual methods internally. 這些虛擬方法都屬於 WPFWPF 屬性系統服務。These virtual methods are part of the WPFWPF property system services. 覆寫方法可讓衍生的類別參與值判斷。Overriding the methods enables derived classes to participate in value determination. 若要避免執行階段初始化可能發生的問題,您不應該在類別的建構函式中設定相依性屬性值,除非您遵循非常明確的建構函式模式。To avoid potential issues with runtime initialization, you should not set dependency property values within constructors of classes, unless you follow a very specific constructor pattern. 如需詳細資訊,請參閱 DependencyObject 的安全建構函式模式For details, see Safe Constructor Patterns for DependencyObjects.

另請參閱See also