附加屬性概觀Attached Properties Overview

附加屬性是透過 XAML 所定義的概觀。An attached property is a concept defined by XAML. 附加屬性是要用作可在任何物件上設定的全域屬性類型。An attached property is intended to be used as a type of global property that is settable on any object. Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) 中,附加屬性一般會定義為沒有傳統屬性「包裝函式」的特殊形式相依性屬性。In Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF), attached properties are typically defined as a specialized form of dependency property that does not have the conventional property "wrapper".

要求Prerequisites

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

為何要使用附加屬性Why Use Attached Properties

附加屬性的其中一個用途是允許不同的子項目指定父項目中實際定義的屬性的唯一值。One purpose of an attached property is to allow different child elements to specify unique values for a property that is actually defined in a parent element. 此情節的特定應用程式可讓子項目通知父項目,有關如何在 使用者介面 (UI)user interface (UI) 中呈現它們。A specific application of this scenario is having child elements inform the parent element of how they are to be presented in the 使用者介面 (UI)user interface (UI). 其中一個範例是DockPanel.Dock屬性。One example is the DockPanel.Dock property. 屬性會建立為附加屬性DockPanel, 因為它是設計來在包含在中的專案上設定, 而不是在其DockPanel本身上。 DockPanel.DockThe DockPanel.Dock property is created as an attached property because it is designed to be set on elements that are contained within a DockPanel, rather than on DockPanel itself. GetDock DependencyProperty DockProperty類別會定義名為的靜態欄位, 然後提供和SetDock方法做為附加屬性的公用存取子。 DockPanelThe DockPanel class defines the static DependencyProperty field named DockProperty, and then provides the GetDock and SetDock methods as public accessors for the attached property.

XAML 中的附加屬性Attached Properties in XAML

在 XAML 中,您可以使用 AttachedPropertyProvider.<屬性名稱> 語法來設定附加屬性。In XAML, you set attached properties by using the syntax AttachedPropertyProvider.PropertyName

以下是您可以如何在 XAML 中設定DockPanel.Dock的範例:The following is an example of how you can set DockPanel.Dock in XAML:

<DockPanel>
  <CheckBox DockPanel.Dock="Top">Hello</CheckBox>
</DockPanel>

請注意, 使用方式與靜態屬性有點類似;您一律會參考擁有DockPanel和註冊附加屬性的類型, 而不是參照任何依名稱指定的實例。Note that the usage is somewhat similar to a static property; you always reference the type DockPanel that owns and registers the attached property, rather than referring to any instance specified by name.

此外,因為 XAML 中的附加屬性是您在標記中設定的屬性,所以只有設定作業才會有任何相關性。Also, because an attached property in XAML is an attribute that you set in markup, only the set operation has any relevance. 雖然有一些間接機制可比較值 (例如樣式中的觸發程序),但是您無法在 XAML 中直接取得屬性 (如需詳細資訊,請參閱設定樣式和範本)。You cannot directly get a property in XAML, although there are some indirect mechanisms for comparing values, such as triggers in styles (for details, see Styling and Templating).

WPF 中的附加屬性實作Attached Property Implementation in WPF

Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF)中, 與 UI 呈現相關的 WPF 類型上存在的大部分附加屬性都會實作為相依性屬性。In Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF), most of the attached properties that exist on WPF types that are related to UI presentation are implemented as dependency properties. 附加屬性是 XAML 概念, 而相依性屬性則是 WPF 概念。Attached properties are a XAML concept, whereas dependency properties are a WPF concept. 由於 WPF 附加屬性是相依性屬性, 因此支援相依性屬性概念, 例如屬性中繼資料, 以及來自該屬性中繼資料的預設值。Because WPF attached properties are dependency properties, they support dependency property concepts such as property metadata, and default values from that property metadata.

擁有類型如何使用附加屬性How Attached Properties Are Used by the Owning Type

雖然可在任何物件上設定附加屬性,但是這不自動表示設定屬性就會產生明確結果,或者另一個物件將使用值。Although attached properties are settable on any object, that does not automatically mean that setting the property will produce a tangible result, or that the value will ever be used by another object. 一般而言,會使用附加屬性,讓來自各種可能類別階層或邏輯關聯性的物件都可以報告可定義附加屬性之類型的通用資訊。Generally, attached properties are intended so that objects coming from a wide variety of possible class hierarchies or logical relationships can each report common information to the type that defines the attached property. 可定義附加屬性的類型通常會遵循下列其中一個模型︰The type that defines the attached property typically follows one of these models:

  • 設計可定義附加屬性的類型,因此它可以是設定附加屬性值之項目的父項目。The type that defines the attached property is designed so that it can be the parent element of the elements that will set values for the attached property. 類型接著會透過內部邏輯針對某個物件樹狀結構逐一查看其子物件,並取得值,然後以某種方式處理這些值。The type then iterates its child objects through internal logic against some object tree structure, obtains the values, and acts on those values in some manner.

  • 可定義附加屬性的類型將會用作各種可能父項目和內容模組的子項目。The type that defines the attached property will be used as the child element for a variety of possible parent elements and content models.

  • 可定義附加屬性的類型代表服務。The type that defines the attached property represents a service. 其他類型設定附加屬性的值。Other types set values for the attached property. 然後,在服務內容中評估可設定屬性的項目時,會透過服務類別的內部邏輯取得附加屬性值。Then, when the element that set the property is evaluated in the context of the service, the attached property values are obtained through internal logic of the service class.

父代已定義的附加屬性範例An Example of a Parent-Defined Attached Property

WPF 定義附加屬性的最常見案例是當父元素支援子專案集合時, 也會執行行為, 其中會針對每個子專案個別報告行為的細節。The most typical scenario where WPF defines an attached property is when a parent element supports a child element collection, and also implements a behavior where the specifics of the behavior are reported individually for each child element.

DockPanel定義附加屬性, 並DockPanel具有類別層級程式碼作為其轉譯邏輯的一部分 (尤其是MeasureOverrideArrangeOverride)。 DockPanel.DockDockPanel defines the DockPanel.Dock attached property, and DockPanel has class-level code as part of its rendering logic (specifically, MeasureOverride and ArrangeOverride). 實例一律會檢查是否有任何直屬子專案已設定的DockPanel.Dock值。 DockPanelA DockPanel instance will always check to see whether any of its immediate child elements have set a value for DockPanel.Dock. 如果是這樣,這些值會變成套用至該特定子項目之轉譯邏輯的輸入。If so, those values become input for the rendering logic applied to that particular child element. DockPanel個嵌套的實例都會處理自己的直屬子專案集合, 但該行為會因DockPanel處理DockPanel.Dock值而異。Nested DockPanel instances each treat their own immediate child element collections, but that behavior is implementation-specific to how DockPanel processes DockPanel.Dock values. 理論上,可能會有附加屬性影響直屬父代以外的項目。It is theoretically possible to have attached properties that influence elements beyond the immediate parent. 如果附加屬性設定在沒有DockPanel父元素的專案上進行動作, 則不會引發錯誤或例外狀況。 DockPanel.DockIf the DockPanel.Dock attached property is set on an element that has no DockPanel parent element to act upon it, no error or exception is raised. 這只是表示已設定全域屬性值, 但目前DockPanel沒有任何可能會耗用此資訊的父系。This simply means that a global property value was set, but it has no current DockPanel parent that could consume the information.

程式碼中的附加屬性Attached Properties in Code

WPF 中附加的屬性沒有一般的 CLR 「包裝函式」方法, 可輕鬆取得/設定存取。Attached properties in WPF do not have the typical CLR "wrapper" methods for easy get/set access. 這是因為附加屬性不一定是設定屬性之實例的 CLR 命名空間的一部分。This is because the attached property is not necessarily part of the CLR namespace for instances where the property is set. 不過,XAML 處理器必須可以在剖析 XAML 時設定這些值。However, a XAML processor must be able to set those values when XAML is parsed. 若要支援有效的附加屬性使用方式, 附加屬性的擁有者類型必須以Get_PropertyName_Set_PropertyName_ 格式來實作為專用存取子方法。To support an effective attached property usage, the owner type of the attached property must implement dedicated accessor methods in the form Get_PropertyName_ and Set_PropertyName_. 這些專用存取子方法也適用於取得或設定程式碼中的附加屬性。These dedicated accessor methods are also useful to get or set the attached property in code. 從程式碼觀點,附加屬性類似具有方法存取子而非屬性存取子的支援欄位,而且該支援欄位可以存在於任何物件,而不需要特別進行定義。From a code perspective, an attached property is similar to a backing field that has method accessors instead of property accessors, and that backing field can exist on any object rather than needing to be specifically defined.

下列範例示範如何在程式碼中設定附加屬性。The following example shows how you can set an attached property in code. 在此範例中myCheckBox , 是CheckBox類別的實例。In this example, myCheckBox is an instance of the CheckBox class.

DockPanel myDockPanel = new DockPanel();
CheckBox myCheckBox = new CheckBox();
myCheckBox.Content = "Hello";
myDockPanel.Children.Add(myCheckBox);
DockPanel.SetDock(myCheckBox, Dock.Top);
Dim myDockPanel As New DockPanel()
Dim myCheckBox As New CheckBox()
myCheckBox.Content = "Hello"
myDockPanel.Children.Add(myCheckBox)
DockPanel.SetDock(myCheckBox, Dock.Top)

類似于 XAML 案例, 如果myCheckBox尚未將第三行程式碼加入為的myDockPanel子項目, 則第四行程式碼不會引發例外狀況, 但屬性值不DockPanel會與父系互動, 因此不會執行任何動作。Similar to the XAML case, if myCheckBox had not already been added as a child element of myDockPanel by the third line of code, the fourth line of code would not raise an exception, but the property value would not interact with a DockPanel parent and thus would do nothing. 只有在子項目上設定的DockPanel 值與父元素的存在結合,才會在轉譯的應用程式中造成有效的行為。DockPanel.DockOnly a DockPanel.Dock value set on a child element combined with the presence of a DockPanel parent element will cause an effective behavior in the rendered application. (在此情況下,您可以設定附加屬性,然後將其附加至樹狀結構。(In this case, you could set the attached property, then attach to the tree. 或者,您可以將其附加至樹狀結構,然後設定附加屬性。Or you could attach to the tree then set the attached property. 任一個動作順序都會提供相同的結果)。Either action order provides the same result.)

附加屬性中繼資料Attached Property Metadata

當註冊屬性時, FrameworkPropertyMetadata會設定為指定屬性的特性, 例如屬性是否會影響轉譯、測量等等。When registering the property, FrameworkPropertyMetadata is set to specify characteristics of the property, such as whether the property affects rendering, measurement, and so on. 附加屬性的中繼資料一般與相依性屬性並無不同。Metadata for an attached property is generally no different than on a dependency property. 如果您在附加屬性中繼資料的覆寫中指定預設值,該值會變成覆寫類別執行個體上的隱含附加屬性預設值。If you specify a default value in an override to attached property metadata, that value becomes the default value of the implicit attached property on instances of the overriding class. 具體而言,如果某個處理序透過該屬性的 Get 方法存取子來查詢附加屬性值,並指定已指定中繼資料之類別的執行個體,則會報告預設值,否則不會設定該附加屬性的值。Specifically, your default value is reported if some process queries for the value of an attached property through the Get method accessor for that property, specifying an instance of the class where you specified the metadata, and the value for that attached property was otherwise not set.

如果您想要啟用屬性的屬性值繼承,則應該使用附加屬性,而不是使用非附加相依性屬性。If you want to enable property value inheritance on a property, you should use attached properties rather than non-attached dependency properties. 如需詳細資訊,請參閱屬性值繼承For details, see Property Value Inheritance.

自訂附加屬性Custom Attached Properties

建立附加屬性的時機When to Create an Attached Property

非定義類別的類別需要有可用的屬性設定機制時,您可以建立附加屬性。You might create an attached property when there is a reason to have a property setting mechanism available for classes other than the defining class. 最常見的案例是配置。The most common scenario for this is layout. 現有版面配置屬性的範例DockPanel.Dock包括Panel.ZIndex、和Canvas.TopExamples of existing layout properties are DockPanel.Dock, Panel.ZIndex, and Canvas.Top. 在這裡啟用的情節是本身為配置控制項目之子項目的項目可以個別表達其配置父項目的配置需求,且各會設定父代定義為附加屬性的屬性值。The scenario enabled here is that elements that exist as child elements to layout-controlling elements are able to express layout requirements to their layout parent elements individually, each setting a property value that the parent defined as an attached property.

另一個使用附加屬性的情節是類別代表一項服務,而且想要類別能夠更緊密地整合服務。Another scenario for using an attached property is when your class represents a service, and you want classes to be able to integrate the service more transparently.

另一種情況是接收 Visual Studio WPF 設計工具支援, 例如 [屬性] 視窗編輯。Yet another scenario is to receive Visual Studio WPF Designer support, such as Properties window editing. 如需詳細資訊,請參閱控制項撰寫概觀For more information, see Control Authoring Overview.

如前所述,如果您想要使用屬性值繼承,則應該註冊為附加屬性。As mentioned before, you should register as an attached property if you want to use property value inheritance.

如何建立附加屬性How to Create an Attached Property

如果您的類別是嚴格定義附加屬性以用於其他類型, 則類別不需要衍生自DependencyObjectIf your class is defining the attached property strictly for use on other types, then the class does not have to derive from DependencyObject. 但是, 如果您遵循整體 WPF DependencyObject模型讓附加屬性也是相依性屬性, 就必須衍生自。But you do need to derive from DependencyObject if you follow the overall WPF model of having your attached property also be a dependency property.

藉由public static readonly宣告類型DependencyProperty的欄位, 將附加屬性定義為相依性屬性。Define your attached property as a dependency property by declaring a public static readonly field of type DependencyProperty. 您可以使用RegisterAttached方法的傳回值來定義此欄位。You define this field by using the return value of the RegisterAttached method. 功能變數名稱必須符合附加屬性名稱 (加上字串Property), 以遵循已建立的 WPF 模式來命名識別欄位與它們所代表的屬性。The field name must match the attached property name, appended with the string Property, to follow the established WPF pattern of naming the identifying fields versus the properties that they represent. 附加屬性提供者也必須提供靜態Get_PropertyName_Set_PropertyName_ 方法, 做為附加屬性的存取子;如果無法這麼做, 就會導致屬性系統無法使用您的附加屬性。The attached property provider must also provide static Get_PropertyName_ and Set_PropertyName_ methods as accessors for the attached property; failing to do this will result in the property system being unable to use your attached property.

注意

如果您省略附加屬性的 get 存取子, 屬性上的資料系結將無法在設計工具中使用, 例如 Visual Studio 和 Expression Blend。If you omit the attached property's get accessor, data binding on the property will not work in design tools, such as Visual Studio and Expression Blend.

Get 存取子The Get Accessor

Get_PropertyName_ 存取子的簽章必須是:The signature for the Get_PropertyName_ accessor must be:

public static object GetPropertyName(object target)

  • target 物件可以指定為實作中的更特定類型。The target object can be specified as a more specific type in your implementation. 例如, DockPanel.GetDock方法會將參數輸入為UIElement, 因為附加屬性僅適用于實例上UIElement的設定。For example, the DockPanel.GetDock method types the parameter as UIElement, because the attached property is only intended to be set on UIElement instances.

  • 傳回值可以指定為實作中的更特定類型。The return value can be specified as a more specific type in your implementation. 例如, GetDock方法會將它輸入為Dock, 因為此值只能設定為該列舉。For example, the GetDock method types it as Dock, because the value can only be set to that enumeration.

Set 存取子The Set Accessor

Set_PropertyName_ 存取子的簽章必須是:The signature for the Set_PropertyName_ accessor must be:

public static void SetPropertyName(object target, object value)

  • target 物件可以指定為實作中的更特定類型。The target object can be specified as a more specific type in your implementation. 例如, SetDock方法會將它輸入為UIElement, 因為附加屬性僅適用于實例上UIElement的設定。For example, the SetDock method types it as UIElement, because the attached property is only intended to be set on UIElement instances.

  • value 物件可以指定為實作中的更特定類型。The value object can be specified as a more specific type in your implementation. 例如, SetDock方法會將它輸入為Dock, 因為此值只能設定為該列舉。For example, the SetDock method types it as Dock, because the value can only be set to that enumeration. 請記住,當這個方法在標記的附加屬性使用方式中遇到附加屬性時,其值是來自 XAML 載入器的輸入。Remember that the value for this method is the input coming from the XAML loader when it encounters your attached property in an attached property usage in markup. 該輸入是指定為標記中 XAML 屬性值的值。That input is the value specified as a XAML attribute value in markup. 因此,您使用的類型必須要有類型轉換、值序列化程式或標記延伸支援,因此,可以從屬性值 (這最後就是一個字串) 建立適當的類型。Therefore there must be type conversion, value serializer, or markup extension support for the type you use, such that the appropriate type can be created from the attribute value (which is ultimately just a string).

下列範例顯示相依性屬性註冊 (使用RegisterAttached方法), 以及Get_PropertyName_Set_PropertyName_ 存取子。The following example shows the dependency property registration (using the RegisterAttached method), as well as the Get_PropertyName_ and Set_PropertyName_ accessors. 在此範例中,附加屬性名稱為 IsBubbleSourceIn the example, the attached property name is IsBubbleSource. 因此,存取子必須命名為 GetIsBubbleSourceSetIsBubbleSourceTherefore, the accessors must be named GetIsBubbleSource and SetIsBubbleSource.

public static readonly DependencyProperty IsBubbleSourceProperty = DependencyProperty.RegisterAttached(
  "IsBubbleSource",
  typeof(Boolean),
  typeof(AquariumObject),
  new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender)
);
public static void SetIsBubbleSource(UIElement element, Boolean value)
{
  element.SetValue(IsBubbleSourceProperty, value);
}
public static Boolean GetIsBubbleSource(UIElement element)
{
  return (Boolean)element.GetValue(IsBubbleSourceProperty);
}
Public Shared ReadOnly IsBubbleSourceProperty As DependencyProperty = DependencyProperty.RegisterAttached("IsBubbleSource", GetType(Boolean), GetType(AquariumObject), New FrameworkPropertyMetadata(False, FrameworkPropertyMetadataOptions.AffectsRender))
Public Shared Sub SetIsBubbleSource(ByVal element As UIElement, ByVal value As Boolean)
    element.SetValue(IsBubbleSourceProperty, value)
End Sub
Public Shared Function GetIsBubbleSource(ByVal element As UIElement) As Boolean
    Return CType(element.GetValue(IsBubbleSourceProperty), Boolean)
End Function

附加屬性 (property) 的屬性 (attribute)Attached Property Attributes

WPF 會定義.NET Framework 屬性.NET Framework attributes數個, 以將附加屬性的相關資訊提供給反映進程, 以及反映的一般使用者和屬性資訊 (例如設計工具)。WPF defines several .NET Framework 屬性.NET Framework attributes that are intended to provide information about attached properties to reflection processes, and to typical users of reflection and property information such as designers. 因為附加屬性的類型為無限制範圍,所以設計人員需要方法來避免使用 XAML 的特定技術實作中所定義之所有附加屬性的全域清單,讓使用者無所適從。Because attached properties have a type of unlimited scope, designers need a way to avoid overwhelming users with a global list of all the attached properties that are defined in a particular technology implementation that uses XAML. WPF .NET Framework 屬性.NET Framework attributes為附加屬性定義的, 可用來界定給定附加屬性應該顯示在 [屬性] 視窗中的情況。The .NET Framework 屬性.NET Framework attributes that WPF defines for attached properties can be used to scope the situations where a given attached property should be shown in a properties window. 您也可以考慮針對您自己的自訂附加屬性套用這些屬性。You might consider applying these attributes for your own custom attached properties also. 適當的參考頁面會描述 .NET Framework 屬性.NET Framework attributes 的用途和語法:The purpose and syntax of the .NET Framework 屬性.NET Framework attributes is described on the appropriate reference pages:

深入瞭解附加屬性Learning More About Attached Properties

  • 如需建立附加屬性的詳細資訊,請參閱註冊附加屬性For more information on creating an attached property, see Register an Attached Property.

  • 如需相依性屬性和附加屬性的更進階使用方式情節,請參閱自訂相依性屬性For more advanced usage scenarios for dependency properties and attached properties, see Custom Dependency Properties.

  • 您也可以將屬性註冊為附加屬性和相依性屬性,但仍公開「包裝函式」實作。You can also register a property as an attached property, and as a dependency property, but then still expose "wrapper" implementations. 在此情況下,可以在該項目上設定屬性,或透過 XAML 附加屬性語法的任何項目上設定屬性。In this case, the property can be set either on that element, or on any element through the XAML attached property syntax. 具有適用于標準和附加用法之適當案例的屬性範例為FrameworkElement.FlowDirectionAn example of a property with an appropriate scenario for both standard and attached usages is FrameworkElement.FlowDirection.

另請參閱See also