How exactly do Attached Properties work in WPF? - wpf

I'm a bit mystified as to how Attached Properties actually convey their values to either parent or child elements. TextElement.FontFamily causes child elements to inherit the value assigned to that property (a seemingly downstream operation, parent to child). Grid.Column causes a parent item to display that child in a particular position (a seemingly upstream operation, child to parent). How do Attached Property values know to either flow up or down? Is my conception of this incorrect, or is there a piece missing that will put all of this into perspective?
<StackPanel TextElement.FontFamily="Wingdings">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="1" Content="My Button"/>
</Grid>
</StackPanel>

There are two concepts here: dependency properties and attached dependency properties. "Attached Properties" are dependency properties, and as such support dependency property value inheritance.
About basic dependency properties, a very rough statement would be that they basically inherit their values from parent elements in the wpf (logical/visual) tree. A dependency property (attached or not) inherits its value "downwards" if its metadata is set with the FrameworkPropertyMetadataOptions.Inherit flag, and in many cases this is so.
Attached properties are properties which can be set on any wpf object (basically, at least a DependencyObject) via the DependencyObject.SetValue method. The purpose for this mechanism is to "attach" to other objects information needed by parent objects, not the child objects themselves. For example, the Grid.Row is an attached property required by the Grid to place items within its render area.
Dependency properties are inherited "downwards" automatically by the wpf object system.
Attached properties are examined "upwards" explicitly, in the code of specific objects. In the case of Grid, upon determining where to place its items, it checks for the value of Grid.Row and Grid.Column attached properties on each contained item.
It is also often the technique to create custom attached properties which modify in some way the objects they are attached to (for example, the Drag'n'Drop functionality via attached properties).
As an additional note, a good example of an inheriting attached property is TextElement.FontFamily. Grid.Row and Grid.Column properties do not have the Inherits flag set.
TextElement.FontFamily, from Reflector:
FontFamilyProperty = DependencyProperty.RegisterAttached("FontFamily", typeof(FontFamily), typeof(TextElement), new FrameworkPropertyMetadata(SystemFonts.MessageFontFamily, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure), new ValidateValueCallback(TextElement.IsValidFontFamily));
Grid.Row, from Reflector:
RowProperty = DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid), new FrameworkPropertyMetadata(0, new PropertyChangedCallback(Grid.OnCellAttachedPropertyChanged)), new ValidateValueCallback(Grid.IsIntValueNotNegative));

From MSDN:
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
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 defines the DockPanel.Dock attached property, and DockPanel has class-level code as part of its rendering logic (specifically, MeasureOverride and ArrangeOverride). A 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. 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. If 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. This simply means that a global property value was set, but it has no current DockPanel parent that could consume the information.

In simple words this is how I understand it (please correct me if I'm wrong).
An object (A) implements a property that will attach to another object (B) (object B doesn't even know about the existence of this "attachable" property). Object B needs to inherit from DependencyObject.
Object A also implements a static method to check for it's "attachable" property in other objects, A.GetAttachedProperty(B).
If B has the attached property from A, A.GetAttachedProperty will read and return it's value. Otherwise A will try to read it, and return null since it's not there.

Related

difference between Attached Property and Dependency property? [duplicate]

What's the difference between a (custom) dependency property and an attached property in WPF? What are the uses for each? How do the implementations typically differ?
Attached properties are a type of dependency property. The difference is in how they're used.
With an attached property, the property is defined on a class that isn't the same class for which it's being used. This is usually used for layout. Good examples are Panel.ZIndex or Grid.Row - you apply this to a control (ie: Button), but it's actually defined in Panel or Grid. The property is "attached" to the button's instance.
This allows a container, for example, to create properties that can be used on any UIelement.
As for implementation differences - it's basically just a matter of using Register vs. RegisterAttached when you define the property.
Abstract
Since I found little to no documentation on the matter, it took some poking around the source code, but here's an answer.
There is a difference between registering a dependency property as a regular and as an attached property, other than a "philosophical" one (regular properties are intended to be used by the declaring type and its deriving types, attached properties are intended to be used as extensions on arbitrary DependencyObject instances). "Philosophical", because, as #MarqueIV noticed in his comment to #ReedCopsey's answer, regular properties can also be used with arbitrary DependencyObject instances.
Moreover, I have to disagree with other answers stating that attached property is "type of dependency property", because it's misleading - there aren't any "types" of dependency properties. The framework doesn't care if the property was registered as attached or not - it's not even possible to determine (in the sense that this information is not recorded, because it's irrelevant). In fact, all properties are registered as if they were attached properties, but in case of regular ones some additional things are done that slightly modify their behavior.
Code excerpt
To save you the trouble of going through the source code yourself, here's a boiled down version of what happens.
When registering a property without metadata specified, calling
DependencyProperty.Register(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass))
yields exactly the same result as calling
DependencyProperty.RegisterAttached(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass))
However, when specifying metadata, calling
DependencyProperty.Register(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass),
typeMetadata: new FrameworkPropertyMetadata
{
CoerceValueCallback = CoerceCallback,
DefaultValue = "default value",
PropertyChangedCallback = ChangedCallback
});
is equivalent to calling
var property = DependencyProperty.RegisterAttached(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass),
defaultMetadata: new PropertyMetadata
{
DefaultValue = "default value",
});
property.OverrideMetadata(
forType: typeof(MyClass),
typeMetadata: new FrameworkPropertyMetadata
{
CoerceValueCallback = CoerceCallback,
DefaultValue = "default value",
PropertyChangedCallback = ChangedCallback
});
Conclusions
The key (and only) difference between regular and attached dependency properties is the default metadata available through DependencyProperty.DefaultMetadata property. This is even mentioned in the Remarks section:
For nonattached properties, the metadata type returned by this property cannot be cast to derived types of PropertyMetadata type, even if the property was originally registered with a derived metadata type. If you want the originally registered metadata including its original possibly derived metadata type, call GetMetadata(Type) instead, passing the original registering type as a parameter.
For attached properties, the type of the metadata returned by this property will match the type given in the original RegisterAttached registration method.
This is clearly visible in the provided code. Little hints are also hidden in the registering methods, i.e. for RegisterAttached the metadata parameter is named defaultMetadata, whereas for Register it is named typeMetadata. For attached properties the provided metadata becomes the default metadata. In case of regular properties however, the default metadata is always a fresh instance of PropertyMetadata with only DefaultValue set (either from provided metadata or automatically). Only the subsequent call to OverrideMetadata actually uses the provided metadata.
Consequences
The main practical difference is that in case of regular properties the CoerceValueCallback and PropertyChangedCallback are applicable only for types derived from the type declared as the owner type, and for attached properties they're applicable for all types. E.g. in this scenario:
var d = new DependencyObject();
d.SetValue(SomeClass.SomeProperty, "some value");
the registered PropertyChangedCallback will be called if the property was registered as an attached property, but will not be called if it was registered as a regular property. Same goes to CoerceValueCallback.
A secondary difference stems from the fact that OverrideMetadata requires that supplied type derives from DependencyObject. In practice it means that the owner type for regular properties must derive from DependencyObject, whereas for attached properties in can be any type (including static classes, structs, enums, delegates, etc.).
Supplement
Besides #MarqueIV's suggestion, on several occasions I've come across opinions that regular and attached properties differ in the way they can be used in XAML. Namely, that regular properties require implicit name syntax as opposed to explicit name syntax required by attached properties. This is technically not true, although in practice it usually is the case. For clarity:
<!-- Implicit property name -->
<ns:SomeClass SomeProperty="some value" />
<!-- Explicit property name -->
<DependencyObject ns:SomeClass.SomeProperty="some value" />
In pure XAML, the only rules governing the usage of these syntaxes are the following:
Implicit name syntax can be used on an element if and only if the class that this element represents has a CLR property of that name
Explicit name syntax can be used on an element if and only if the class specified by the first part of the full name exposes appropriate static get/set methods (referred to as accessors) with names matching the second part of the full name
Satisfying these conditions enables you to use corresponding syntax regardless of whether the backing dependency property was registered as regular or attached.
Now the mentioned misconception is caused by the fact that vast majority of tutorials (together with stock Visual Studio code snippets) instruct you to use CLR property for regular dependency properties, and get/set accessors for attached ones. But there's nothing stopping you from using both at the same time, allowing you to use whichever syntax you prefer.
Attached properties are basically meant for the container elements.like if you have a grid and you have grid.row now this is considered to be an attached property of a grid element.also you can use this property in texbox,button etc to set its place in the grid.
Dependency property is like the property basically belongs to some other class and is used in other class.
eg: like you have a rectangle
here height and width are regular properties of rectangle,but left and top are the dependency property as it belongs to Canvass class.
Attached properties are a special kind of DependencyProperties. They allow you to attach a value to an object that does not know anything about this value.
A good example for this concept are layout panels. Each layout panel needs different data to align its child elements. The Canvas needs Top and Left, The DockPanel needs Dock, etc. Since you can write your own layout panel, the list is infinite. So you see, it's not possible to have all those properties on all WPF controls.
The solution are attached properties. They are defined by the control that needs the data from another control in a specific context. For example an element that is aligned by a parent layout panel.
I think you can defined attached property in the class itself or you can define it in another class. We always could use attached property to extend standard microsoft controls. But dependency property, you define it in your own custom control. e.g. You can inherit your control from a standard control, and define a dependency property in your own control and use it. This is equivalent to define an attached property, and use this attached property in the standard control.

When are the elements of a ContentProperty actually created?

I am creating a custom WPF control that uses the following markup:
<custom:FilterPanel
Grid.Row="1"
FilterTarget="{Binding Path=MyItems}">
<custom:FilterParameter
ParameterName="Name"
TargetProperty="Name" />
<custom:FilterParameter
ParameterName="Date"
TargetProperty="MyDate" />
</custom:FilterPanel>
I've set the ContentProperty for my FilterPanel to FilterParameters, which is obviously a collection of FilterParameter objects that I add items to using the markup above. My question is, when are the elements of a ContentProperty actually processed so that instances are created and items are actually added to the underlying collection?
I'm interested in sharing the data source of the parent control with its children, is there any point in the WPF lifecycle where I can override this behavior and add custom logic to the creation of this collection of FilterParameters?
Assuming your class derives from Panel, then the first point in the Panel's lifecycle where you can see children (i.e. children that are decalred in XAML like your example - not children generated via bindings) is Panel.EndInit(), a virtual method you can override in your derived class. Specifically the chldren created between the BeginInit and EndInit methods.

How can an AttachedProperty have multiple values?

How can an AttachedProperty which is a single property defined by an owning parent element, be set with multiple values through several child elements of that parent?
For example:
If I have:
<DockPanel>
<CheckBox DockPanel.Dock="Top">Hello</CheckBox>
<CheckBox DockPanel.Dock="Bottom">World</CheckBox>
</DockPanel>
Here we have a single DockPanel element and it has a single Dock property. How can it be set to "Top" and then "Bottom" simultaneously?
It will end up in a method looking like this
public class DockPanel : Panel
{
public static readonly DependencyProperty DockProperty;
// ...
public static void SetDock(UIElement element, Dock dock)
{
element.SetValue(DockProperty, value);
}
}
As you can see, it's actually not set on the parent, but the CheckBox itself, through the static method SetDock on DockPanel and not the parent instance. Doing it in code behind makes this a little clearer, notice how we never use an instance of a DockPanel.
DockPanel.SetDock(checkBox1, Dock.Top);
DockPanel.SetDock(checkBox2, Dock.Bottom);
Hopefully this was clear, unless your question was how this works "under the hood". In that case, see this question.
Quote from link.
The purpose for this mechanism is to
"attach" to other objects information
needed by parent objects, not the
child objects themselves.
A CheckBox has no use for a Dock property unless it is in a DockPanel. Same goes for Grid.Row, Canvas.Left, Validation.HasError (read only) etc. So basically, the DockPanel is the one needing the information, but it needs all its childs to be able to store it. Hence, it's using an Attached Property for it. If you created a new Panel, called PuneetPanel, and you needed an Angel to calculate the child position, then you could define your own Attached Property, PuneetPanel.Angel inside this panel and all childs could use this without having to be subclassed.
This is a very nice question. The answer lies in how the AttchedProperty works. The AttachedProperty is used by the parent to render a child. Before rendering the child, the parent looks out for any attached property defined on child and applies to the child.
I found this from msdn which might be useful for you ::
DockPanel defines the DockPanel.Dock attached property, and DockPanel has class-level code as part of its rendering logic (specifically, MeasureOverride and ArrangeOverride). A 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....
You can see this link to get detailed overview ::
http://http://msdn.microsoft.com/en-us/library/ms749011.aspx
Hope it helps you!!
For your own custom attached properties there are two options to achieve what you are looking for:
1. If the number of combinations of settable values are not to complex you could make your attached property of type enum that has the FlagsAttribute set. You can the combines the values you want to set using bitwise-or |:
[Flags]
public enum MultiDock
{
Left,
Top,
Right,
Bottom
}
And its usage in code:
MyCustomPanelOrWhatever.SetMultiDock(MultiDock.Left | MultiDock.Bottom);
This has one small proplem though, you can not do the above in xaml directly, you would have to write a MarkupExtension that can convert string to flagged enum values. Its usage would then look like this:
<CheckBox src:MyCustomPanelOrWhatever.MulitDock="{src:FlaggedEnum Left|Bottom}" />
2. Since attached properties can be of any type, they can of course also be complex types (with multiple subproperties) or even collections, so it is easily possible to do something like this:
MyCustomPanelOrWhatever.SetMultiDock(new List<MultiDock> { MultiDock.Left, MultiDock.Bottom });
If you have defined your attached property that way, you do not need any converters for xaml, you can use it directly:
<CheckBox>
<src:MyCustomPanelOrWhatever.MultiDock>
<src:MultiDock.Left/>
<src:MultiDock.Bottom/>
</src:MyCustomPanelOrWhatever.MultiDock>
</CheckBox>

WPF: Bindings - Object not updated

I have a an object which is set to the DataContext in a Window. I have textboxes in the window which are bound to the properties on the object. There seems to be a delay however before the properties on the object are updated.
<TextBox x:Name="txtPropertyOne" Text="{Binding Path=PropertyOne,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
If I change the values in a few textboxes then quickly try to access the properties to which they map, sometimes there are changes which aren't reflected in the properties of the object. I thought that was what the PropertyChanged UpdateSourceTrigger was supposed to take care of.
If I change the values in a few
textboxes then quickly try to access
the properties to which they map
I can interpret this statement in two ways:
You're trying to access the values on a background thread. In that case, you may be accessing the properties before the UI thread has had a chance to do its thing.
You're using a separate message on the UI thread to check the values. Bindings are updated at a priority lower than Send and Normal. So if your message is priority Send or Normal it will be processed before any pending binding updates.
If this doesn't answer your question, please clarify what you mean by "quickly trying to access the properties".
The basic rule of WPF Databinding is simple:
The target property must be a
dependency property, and you're
already correct, it's bound to Text
property of TextBox.
The source property can be a CLR
object (other than any derived WPF's
DependencyObject), but the object
must employ or implement its own
INotifyPropertyChanged.
Have you you already implemented INotifyPropertyChanged on your object?

Automatically creating child objects during Silverlight DataBinding?

I have a parent object of type Parent and it currently has a null property called Foo of type Child and that Child class has a property of type string called Name.
If the user types into a Text Box for that Name property then I want to automatically create an instance of Child and set it as the Foo property of Parent before finally setting the Name property of the Child object.
If i use:
{Binding parent.foo.name, Mode=TwoWay}
It doesn't create foo and essentially does nothing. Is there any way to achieve what I want without pre-creating all the possible child objects and then removing them if properties haven't been set?
There is no automatic way. You could consider using a pattern like M-V-VM and handling this logic in the ViewModel. You might also possibly get creative with an IValueConverter so that your binding can run custom code when the value is set. But WPF / Silverlight binding will not automatically do this work for you.

Resources