Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How exactly do Attached Properties work in WPF?

Tags:

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> 
like image 281
Mark Carpenter Avatar asked Jul 23 '09 18:07

Mark Carpenter


People also ask

What is an attached property in WPF?

An attached property is a Extensible Application Markup Language (XAML) concept. Attached properties enable extra property/value pairs to be set on any XAML element that derives from DependencyObject, even though the element doesn't define those extra properties in its object model.

What is the use of dependency property in WPF?

The purpose of dependency properties is to provide a way to compute the value of a property based on the value of other inputs, such as: System properties, such as themes and user preference. Just-in-time property determination mechanisms, such as data binding and animations/storyboards.

Why dependency property is static readonly in WPF?

Using the readonly keyword has at least three effects: it informs readers of the code that the value will not change. it prevents the author from accidentally changing the value. it assists the compiler, which benefits from knowing when things will not change.


1 Answers

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)); 
like image 172
Kenan E. K. Avatar answered Sep 22 '22 13:09

Kenan E. K.