Attached properties
Attached properties were probably the very first technology we invented for WPF. Back in late 2000, before WPF/avalon even existed, Jeff Bogdan and I were doing some prototyping, and we ran into a problem -- every layout had a set of properties that it wanted on the elements it's laying out. DockPanel wants each child element to have a Dock property, GridPanel wants each child to have Row & Column, etc.. But we wanted an extensible set of layouts, so we couldn't just add all these properties to the base class (then called Control I believe). We considered a couple other models. Scripting languages allow you to create arbitrary properties at any time, with the downside that if you make a typo, you get a new property you never intended. That wasn't cool... We also looked at Windows Forms' concept of extender providers:
SomeProvider provider = new SomeProvider();
provider.SetDock(button, Dock.Fill);
This had the strong typing we were looking for, but there was a lifetime management issue. Because the data storage was part of the extender provider, rather than the target element, they really didn't work very well with styles (when do you dispose of the extender provider? After the last style usage is gone? Way too much work to track!). So we invented the notion of attached properties, and convinced Mark Finnocchio to embed this concept deeply into the fledgling property engine.
These days, there's almost two completely different ways to look at attached properties. From the property engine perspective, all properties are potentially attachable (although as an optimization, some classes provide built-in storage for particular properties). But from a parser perspective, those "CLR wrappers" make a big difference. The property engine couldn't care less whether you wrote
int Dock { get; set; }
or
int GetDock(DependencyObject o);
void SetDock(DependencyObject o, int value);
Or even didn't write them at all and asked people to use SetValue(DockProperty). But the parser cares -- it won't let you use attached property syntax for non-attached properties. Because the parser tries not to understand dependency properties, it would rather just set Dock or call SetDock, not deal with some funny SetValue thing. As, for that matter, would most users.
But from a property engine perspective, there's really just attached properties. You can call panel.SetValue(CheckBox.CheckedProperty, true), and property engine will happily set that attached property to true. Doesn't matter that nobody is ever going to try to read that property value (setting a property doesn't mean someone cares), doesn't matter that the author of CheckBox probably never intended this, you're free to do it.
That's worth repeating -- in the typical layout example:
<DockPanel>
<Button DockPanel.Dock="top"/>
</DockPanel>
From a property engine perspective, it's irrelevant that Button happens to be inside a DockPanel perspective. You could set DockPanel.Dock even if your parent is a Grid -- that property won't do any good, because Grid doesn't look at the DockPanel.Dock property, but you can do it.
One of the other more obscure things about attached properties is that DependencyProperty.Register() and RegisterAttached() aren't actually all that different. Both create properties that are capable of being attached, the only difference is that Register() associates the property metadata with the type you actually care about (e.g., CheckBox for the Checked property), whereas RegisterAttached applies the property metadata to all DependencyObjects. We do this mostly so when controls like CheckBox include an invalidation callback, inside that callback they are free to cast the DO to a CheckBox, because with the metadata registered where it is, the property engine won't call them if someone does panel.SetValue(CheckBox.CheckedProperty, true).
Comments
- Anonymous
August 24, 2005
Last time I looked, DependencyProperty wasn't generic, and there was much casting and boxing of ints and doubles going on. Code would absolutely benefit from a DependencyProperty<T>, but wouldn't also performance? I would just like to hear that you at least measured...
Anyway, attached props is a nice concept and I think it could have a place even outside of a UI framework. Maybe add some syntactic sugar in C# 3.0 to make them easier to implement, while you're at it? - Anonymous
September 04, 2005
Image Scaling
Attached properties
XAML Editing in an Xml Editor - major schema enhancement coming... - Anonymous
February 09, 2006
A&nbsp;post on the Avalon Forum&nbsp;from Jaffi raised a question
WPF is not straight forward. Simple... - Anonymous
June 19, 2006
While researching for information about Avalon [for play-n-learn sample&nbsp;app], I realized&nbsp;that...