Attached Behaviors vs Attached Properties vs Blend Behaviors

Brian Lagunas asked a very good question based on seeing my sample video from my Pluralsight Windows 8 MVVM XAML Apps course, the gist of which was (paraphrased): “Why do you call them Attached Behaviors – won’t that cause confusion with what is an Attached Property and with Blend Behaviors?”

My initial answer was along the lines of “because that is what we called them back in the day, long before Blend picked up the concept and created their own behaviors.”

http://blogs.msdn.com/b/dancre/archive/2006/03/04/543854.aspx

But Brian rightly pointed out that not everyone has as deep of history working with XAML as I do and a lot of people only associated the term behavior with Blend Behaviors. He also asked how to discriminate a simple attached property from an attached behavior.

Here is my response:

I think the distinction in my mind is this: "normal" attached properties are there as metadata for some other piece of code (i.e. a container control like a Grid or a ToolTip) to modify its own behavior based on the presence of that attached property. When used like that, attached properties are like attributes in C# or VB code – they don’t do any work themselves, they are just there to influence behavior implemented somewhere else.

When an attached property has a change handler that acts on the exposed API of the DependencyObject to which it is attached, it is an attached behavior – in which case it is much more like an extension method in C# – a chunk of code that can be associated with that object to supplement that object’s behavior or functionality without that object’s knowledge.

A similar discussion also recently came up while working with the Microsoft patterns & practices Kona team on Line-Of-Business guidance for Windows 8. As a result of that discussion, I wrote up a couple page summary with some snippets to compare and contrast Attached vs Blend Behaviors. So I’m including that content here as well.

Attached and Blend Behaviors

Behaviors are a way of supplementing the functionality, or behavior, of XAML elements. A behavior is a chunk of code you write that can be used in XAML by attaching it to some element through attached properties. The behavior can use the exposed API of the element to which it is attached to add functionality to that element or other elements in the visual tree of the view. In this way, they are the XAML equivalent of C# extension methods. Extension methods allow you to define additional methods for some class in C# without modifying the class definition itself, and they work against the exposed API of the class. Behaviors allow you to add functionality to an element by writing that functionality in the behavior class and attaching it to the element as if it was part of the element itself.

Ultimately behaviors package up code that you would normally have to write as code behind because it directly interacts with the API of XAML elements in a way that it can be concisely hooked up to an element in the XAML and packaged for reuse across more than one view or application. They can be used to encapsulate a complex coding pattern of interaction for a given control, do visual tree walks to discover and hook things up throughout a view, and virtually any scenario where you ask yourself “how do I do XYZ?” and the answer is “you write this code behind”. In the context of MVVM, they are a great way to bridge from things that are happening in the view due to user interaction and getting the information and execution into a view model. So you can hook events and properties from a given control type and feed those down into a view model in a standardized fashion.

All behaviors are in some sense “attached behaviors” because they use Attached Properties in XAML to hook the behavior in to some element within the XAML. But two styles of implementation for behaviors are dominant. The first is generally referred to as simply an Attached Behavior, and the second as a Blend Behavior.

Attached Behaviors

Attached behaviors are defined as a static class with one or more Attached Properties defined within it. An Attached Property can define a change callback handler for when the property gets set on some target element, and the callback handler gets passed a reference to the element on which it is being attached (much like the “this” parameter reference in an extension method) and an argument that tells what the old and new values for the property are. The “behavior” comes in when you use that change callback handler to wire up new functionality to the element the property is attached to by manipulating the reference to it that gets passed in. The typical pattern is that the change callback handler will cast the element reference (which comes in as just a DependencyObject) to some known element type that the behavior is designed to enhance. Then it will hook up to events exposed by that element type, modify properties of the element, or call methods on the element to manifest the “behavior” desired.

An example would be to cast the reference to the ListViewBase type in WinRT, which is the base class for GridView and ListView, then subscribe to the ItemClick event, and in the handler for that event, make something happen like navigation or invoke a command.

The syntax for the behavior would look like this:

publicstaticclass ItemClickNavBehavior

{

publicstaticstring GetDestination(DependencyObject obj)

{

return (string)obj.GetValue(DestinationProperty);

}



publicstaticvoid SetDestination(DependencyObject obj, stringvalue)

{

obj.SetValue(DestinationProperty, value);

}



publicstaticreadonly DependencyProperty DestinationProperty =

DependencyProperty.RegisterAttached("Destination", typeof(string),

typeof(ItemClickNavBehavior), new PropertyMetadata(null,

HookupBehavior));



privatestaticvoid HookupBehavior(DependencyObject d,

DependencyPropertyChangedEventArgs e)

{

ListViewBase lvb = d as ListViewBase;

if (lvb == null) return;

lvb.ItemClick += DoNavigation;

}



privatestaticvoid DoNavigation(object sender, ItemClickEventArgs e)

{

//...

}

}

And the hookup for the behavior in the XAML like this:

<GridViewlocal:ItemClickNavBehavior.Destination="Home" ...>



Blend Behaviors

The problem with Attached Behaviors as described above is that they are defined entirely through a set of public static variables and methods within a static class. As a result, there is not good encapsulating, and you have to be very careful with unsubscribing from events that you subscribe to at the appropriate time so you do not cause memory leaks. Additionally, they are not easy to use in a visual designer because there is not a visual designer metaphor for dragging and dropping a property onto an element. You can drag and drop objects on other objects to set up a hierarchy, and you can set properties on objects already in the designer through the properties window, but you cannot do the initial hookup through existing interaction patterns in a designer.

As a result, the Microsoft Expression Blend team standardized a new coding structure for defining behaviors that is both design tool friendly, and is better encapsulated. With a Blend Behavior, you define a non-static class as your behavior , derived from a Behavior or Behavior base class. In your behavior you override a base class method called OnAttached, and you have a base class property called AssociatedObject that gives you a reference to the element to which the behavior is attached. The behavior then gets attached to the element through an Attached Property that is a collection of Behaviors. This allows a drag and drop interaction in a visual designer. You drag and drop the behavior onto the element that you want to attach it to, and an instance of the behavior class is created in the Behaviors Attached Property collection on the target element.

With a Blend Behavior, the syntax for defining one for the same scenario as the Attached Behavior shown earlier looks like this:

publicclass ItemClickNavBehavior2 : Behavior

{

publicstring Destination

{

get { return (string)GetValue(DestinationProperty); }

set { SetValue(DestinationProperty, value); }

}



publicstaticreadonly DependencyProperty DestinationProperty =

DependencyProperty.Register("Destination", typeof(string),

typeof(ItemClickNavBehavior2), new PropertyMetadata(null));



protectedoverridevoid OnAttached()

{

base.OnAttached();

AssociatedObject.ItemClick += DoNavigation;

}

privatevoid DoNavigation(object sender, ItemClickEventArgs e) { /* ... */ }

}



And the attaching code looks like this:

<GridView>

<i:Interaction.Behaviors>

<local:ItemClickNavBehavior2Destination="Home"/>

i:Interaction.Behaviors>

GridView>





The base classes and the attached property class for Blend behaviors come out of the Blend SDK. Unfortunately this is not available for WinRT yet. There are several community developed replacements for it, such as the WinRtBehaviors project. Those use the exact same syntax and structuring as Blend behaviors, just a different namespace so the code can be portable to a Blend SDK once one is released for WinRT. As a result, I would still refer to these as “Blend Behaviors”.

The Blend SDK also ships with a number of pre-built, general purpose behaviors such as InvokeCommandAction, CallMethodAction, and ChangePropertyAction that can be used in MVVM scenarios. These behaviors actually get attached through a Triggers attached property collection instead of Behaviors because they get defined as a pair of objects – a Trigger object such as an EventTrigger, DataTrigger, TimerTrigger and so on, and the associated Action that will be invoked when the trigger fires.

So in the end, even Blend Behaviors are hooked up with an attached property.

Hope that makes it all clear as mud. Smile