The Attached Behavior pattern

My favorite feature of WPF (desktop and web versions) is attached properties. It would be good enough if attached properties merely enabled things like keeping layout properties (Canvas.Left) organized by the type of container rather than the type of content, but they also enable a great little design pattern: Attached Behavior.

Nikhil recently blogged about behaviors in terms of Silverlight (http://www.nikhilk.net/Silverlight-Behaviors.aspx), but of course the same technique is available in desktop WPF and we widely used it during Expression development. Nikhil describes the technique well, but let me reiterate in Design Patternese:

The Attached Behavior pattern encapsulates "behavior" (usually user interactivity) into a class outside the visual heirarchy and allows it to be applied to a visual element by setting an attached property and hooking various events on the visual element.

One of the first behaviors we wrote in Blend was the ClickBehavior. The M-V-VM pattern uses Commands instead of events in many cases, but WPF controls don't trigger Commands in all the interesting cases. Button for example has a Command property, but it only fires when the Button is clicked, not double-clicked or right-clicked. ClickBehavior defines attached properties like DoubleClickCommand of type Command. When you set these properties the behavior registers for the MouseRightButtonUp event and in the handler for that event invokes the Command in the DoubleClickCommand behavior. Interestingly, this same behavior can be used to attach Commands to *any* UIElement, even a rectangle. This turns out to be useful for adding interactivity to parts of the UI without the extra cost of a full-blown Control.

You can do a lot with the Attached Behavior pattern. Drag and drop is an obvious candidate for a behavior. A single DragDropBehavior class can register for all the basic input events and invoke Commands like OnDrop and OnDrag, allowing you to make any visual a DropTarget or DropSource without sub-classing or adding substantial code to your page. As I mentioned in my previous post, Silverlight's Parts and States model does not work easily with the built-in desktop WPF controls because those controls do not trigger the state changes. An attached behavior can hook the right events and do the state transitions...the first prototype of the Silverlight model was written in desktop WPF as an attached behavior.

Caliburn uses the same pattern to add most of its functionality. It’s used to enable MVP, loosely coupled ui composition, ui state persistence, lazy module loading, etc. This would all be possible without attached properties, however it would be much more painful. So, I was very glad when attached properties showed up in the SL 2 Beta 1.

Thanks for your response on the other post about ICommand and I look forward to seeing your example.

I do have another question about Behaviors that seems to be an issue with SL that you might be able to provide some background on if you are willing.

In the desktop framework, DependencyObject has a .ctor() that is public but in SL, you have to go all the way down the inheritance tree to System.Windows.Controls.Control to find a public .ctor()

Why is that? I am running into this in using Prism on SL also, not just with behaviors.

In addition there is a mismatch between the apis for DepenencyProperty.RegisterAttached between desktop and SL that seems to require two different codebases (#if SILVERLIGHT…#else….$endif) which I really don’t like.

In Beta 2 (coming soon), you will find the RegisterAttached API difference has been fixed. We have not made DO.ctor() public on the principal of exposing the least surface area possible, but this has proven problematic. What is the exact scenario you have for wanting your own DO subclass?

So far I have run into it twice, three times if you count the Behavior subclass from Nikhil’s article.

1(&2). I was implementing Behaviors myself and was trying to subclass DependencyObject when I ran into your article which linked me to Nikhil’s. Like my implementation he was forced to sub-class from Control in SL.

2. I am doing some spikes involving creating some base classes for use in a MVVP DataModel where the base class for the Data Model objects is a DependencyObject. Now I am not even sure this ia good idea at this point which is why I am asking. 🙂

As a more general point I am finding the constrained SL API’s somewhat challenging to use not because I can’t figure out how to do what I want but because many of the programming idoms that make up the ‘.NET WAY" have changed and there is no clear commentary on what to replace it with. Case(s) in point:

* ICommand – pattern is good, Desktop implementation of RoutedEvents is complicated, but no ICommand interface – what now?

* SerializableAttribute – Replaced with the preferd WCF Serialization which is good but it did take a bit to figure that out. And of course it leave me with incompatible desktop code unless I move everything over to use DataContract. The DLR on SL even duplicates this attribute in its own assembly (Microsoft.Scripting)

* StringSplitOptions – again missing from SL and duplicated in DLR

* there are more…

Please understand I am NOT complaining. Just trying to understand the new SL pattern guidance, which is why I was really glad to find your blog because it appears you are starting to answer some of those questions.

I have implemented code on the desktop to do that but when porting to SL I run into a problem because AsyncOperation and AsyncOperationManager classes don’t exist. It appears special versions of them do exist for ClientBase WCF calls but they are not general use and they are internal.

Again, this is not a matter of asking that these classes be put back but simply trying to figure out what ‘pattern’ should be used to implement Async API’s that are usable on both desktop and SL.