My previous blog entry focused on dependency properties. In that entry I briefly mentioned a type of dependency property called the attached property. This entry explores attached properties in detail.
Attached properties are a special form of dependency property. They exist so that a child element can store a value associated with a property defined on an ancestor element. This is commonly used in the interaction between elements and the WPF layout infrastructure, such as an element informing a DockPanel that it should be docked to a particular side of the panel. The value which an element has for an attached property is stored by that element, not by the element which exposes the attached property. This is in stark contrast with the extender provider model used in WinForms, where the “extended” property only appeared to exist on other controls, but the backing store actually existed on the object which defined the extended property.
Using attached properties in XAML is very intuitive. The following example shows how the DockPanel.Dock attached property can be set on any element (in this case, a Button) within a DockPanel.
<Button x:Name=”btn” DockPanel.Dock=”Left”/>
The equivalent C# code for setting the attached Dock property on a Button is:
DockPanel.SetDock( btn, Dock.Left );
Both of the code snippets above express the same thing; the Button should be docked to the left side of the DockPanel in which it exists. What is not expressed in the code is that if the Button is not contained within a DockPanel then the setting has no effect. This is consistent with the semantics of attached properties in general: if the property setting has no meaning in a given context, it is ignored.
Attached properties differ from normal dependency properties in several ways. The most noticeable is that they are not wrapped in CLR properties (i.e. standard .NET properties). There is no class in which it would make sense to declare the CLR property for an attached property. If the CLR property were on the class which exposes the attached property, there would be no way to associate different values for different elements. On the other hand, the CLR property could not be defined on all possible classes which might use the attached property, simply for practical reasons.
The solution to the problem of how attached properties should be declared lies in a method naming convention. An attached property named Foo exposed by the Bar class would be exposed by two static methods in the Bar class definition, one called SetFoo and the other called GetFoo. The setter must have two parameters: the first is the element for which the value is being set (usually of type UIElement) and the second is the actual value of the attached property for that element. The getter simply takes the element for which the value is to be retrieved and returns the associated value. The WPF property system looks for methods which follow that naming convention when dealing with attached properties.
Other differences between attached properties and normal dependency properties include the methods used to register them with the property system (DependencyProperty.RegisterAttached and .RegisterAttachedReadOnly instead of .Register and .RegisterReadOnly), and where the property values are stored (on the element which consumes the property instead of the element which declares the property).
To learn more about attached properties, read the Attached Properties Overview page in the Windows SDK.