I am a little confused about WPF attached properties. When you use an attached property that attached property can only be read and used by the class that defines it correct? For example if I wanted to use some attached property as a hover color on a button, can I get the attached property value from the button's template, and will I be able access the attached property from the button to set the hoover color?
-
1All the answer are pretty much everything you need, so i want to add my favorite use of attached properties called, [attached behaviors](http://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF). We use them a whole lot, because we can "inject" custom logic into controls which we would need to overwrite otherwise. So we can mix and combine attached behaviors without the need to careful construct a class hierarchy. For example, a custom TreeViewService.AllowSelectOnRightClick is one good example of an attached behavior. – dowhilefor Mar 16 '13 at 13:19
2 Answers
Adding to the answer from H.B. using an example:
For example if I wanted to use some attached property as a hover color on a button, can I get the attached property value from the button's template, and will I be able access the attached property from the button to set the hover color?
Yes, you sure can. Say that you have an Attached Property called HoverBrush
defined in a class called SomeClass, you can set the value on the instance and bind to it in the template
<StackPanel>
<StackPanel.Resources>
<ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
<Border x:Name="border" Background="Gray">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border"
Property="Background"
Value="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=(local:SomeClass.HoverBrush)}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</StackPanel.Resources>
<Button Content="Blue Hover"
local:SomeClass.HoverBrush="Blue"
Template="{StaticResource MyButtonTemplate}"/>
<Button Content="Green Hover"
local:SomeClass.HoverBrush="Green"
Template="{StaticResource MyButtonTemplate}"/>
</StackPanel>
The attached property in question is defined like this
public class SomeClass
{
public static DependencyProperty HoverBrushProperty =
DependencyProperty.RegisterAttached("HoverBrush",
typeof(Brush),
typeof(SomeClass),
new PropertyMetadata(null));
public static void SetHoverBrush(DependencyObject obj, Brush value)
{
obj.SetValue(HoverBrushProperty, value);
}
public static Brush GetHoverBrush(DependencyObject obj)
{
return (Brush)obj.GetValue(HoverBrushProperty);
}
}

- 5,095
- 5
- 55
- 89

- 83,499
- 23
- 264
- 266
-
in the template when you say SomeClass.HooverBrush how does it know to get the value that was set by the button, what if I have a textbox that is also setting SomeClass.HooverBrush, what keeps the relation? – mihajlv Aug 22 '11 at 14:50
-
@mihajlv: The code is inside the delaration of a control, so the parser sets the value on the dictionary of that control. This is equivalent to calling `SomeClass.SetHoverBrush(TheControlInQuestion)` in code. – H.B. Aug 22 '11 at 14:58
-
@H.B.: so inside the binding it is actually accessing the dictionary of that control (the templated parent) witht a key of SomeClass.HooverBrush? – mihajlv Aug 22 '11 at 15:02
-
@mihajlv: Basically, yes. This might be an oversimplification though as i do not know all the details (also there are dictionaries [at several levels](http://msdn.microsoft.com/en-us/library/ms743230.aspx), e.g. styles) – H.B. Aug 22 '11 at 15:06
-
Have you read the overview? If not, do it.
Attached properties, like dependency properties, just register another key that can be used in the properties dictionary of controls. You can set values anywhere and you can retrieve them anywhere, they are not restricted by type. This means that you may only want it to be set on Buttons but it can be set on TextBoxes too.
Every control has its own dictionary of property keys and values, an attached property allows you to write a value to those dictionaries using a new key. As those dictionaries are independent they can have separate values for the same property which is set and accessed via the static field property declaration.
As those properties are attached you will have to get the values via the GetValue
(as the classes cannot provide a CLR-wrapper themselves).
-
1Adding on to this, attached properties are useful for getting child controls to have a certain property (like setting the font on all children) when the parent control doesn't define that property (a stackpanel doesn't define a font). – N_A Aug 22 '11 at 14:34
-
so even though they are static, each UIElement that uses the att.prop. has an instance of it, because if I use the same property on the text box and the button do they each have an instance, i thought it was static. – mihajlv Aug 22 '11 at 14:34
-
3@mihajlv: Only the property field is static, the values for the controls are saved in individual dictionaries on each control. The field only registers the key that is used for that property. – H.B. Aug 22 '11 at 14:35
-
what do you mean by key? i know the concept of keys and dictionaries but what does it stand for in this context? i don't think i have to register the property on the button so I can use it, from what i am getting from the overview, i can just use it correct? – mihajlv Aug 22 '11 at 14:41
-
@mihajlv: Well, it's more of an interface actually, the field is the interface that allows you to set values in the internal dictionaries of a control, it tells the system "Here's a new property which is called X and can contain Y", you then can set that property on any control using this interface which writes the value to the dictionary of that control using the key X. – H.B. Aug 22 '11 at 14:50
-
i see what you are saying so it is using the property name of the att.prop. as the key storing it as a resource, correct me if I am wrong. thanks for all the help. – mihajlv Aug 22 '11 at 14:58
-
@mihajlv: Well, you are not using the key yourself, you tell WPF to use it to store your value, the dictionaries for that are inaccessible and different from the [normal resources](http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.resources.aspx). Also read the [DP overview](http://msdn.microsoft.com/en-us/library/ms752914.aspx) please. – H.B. Aug 22 '11 at 15:05