The Attached Behavior Pattern

With new technologies often completely new patterns emerge as people try to check-out how far a technology might take them. One interesting example for this is the Attached Behavior Pattern which seems to get a lot of attention in the WPF and Silverlight community lately. It’s a great example of what you can do with those technologies that was previously only very hard to achieve (although sometimes in my calm moments it feels a little bit like a hack to me).

Anyway, here is what the pattern actually does:

The Attached Behavior Pattern uses the moment when an attached DependencyProperty is attached to a DependencyObject in order to wire event handlers to it. With this you’re able to extend the behavior of elements in the WPF trees with arbitrary code.

Let’s take a look at how this can be achieved. First of all we need a class deriving from DependencyObject in order to be able to provide an attached DependencyProperty. It uses the standard pattern of registering the IsEnabled DependencyProperty in the static constructor (which is a bit clunky, btw).

    public class MyBehavior : DependencyObject
    {
        public static readonly DependencyProperty IsEnabledProperty;

        static MyBehavior ()
        {
            IsEnabledProperty = DependencyProperty.RegisterAttached(
                "IsEnabled", //Name of the property
                typeof(bool),//Type of the attached property
                typeof(MyBehavior),//Type of the class that provides the property
                new FrameworkPropertyMetadata(false)); //Default value
        }

        public bool IsEnabled
        {
            get { return this.GetValue<bool>(IsEnabledProperty); }
            set { SetValue(IsEnabledProperty, value); }
        }
    }

Pretty standard stuff so far. However you can use another constructor of FrameworkPropertyMetdata in order to supply a callback which is called when the value of the attached property changes.


	IsEnabledProperty = DependencyProperty.RegisterAttached(
                "IsEnabled", //Name of the property
                typeof(bool),//Type of the attached property
                typeof(MyBehavior),//Type of the class that provides the property
                new FrameworkPropertyMetadata(false, OnBehaviorEnabled)); //Default value + Callback

Next thing we need to do is to configure this attached property on the DependencyObject we want to attach behavior to. This is preferably done in XAML. You’ve got at least two options for doing the configuration. The first option is to set your attached property in the XAML file of a UserControl, Page or Window directly at the source, the element you want to attach behavior to.


<TextBox myNamespace:MyBehavior.IsEnabled="true" />

The other option is to use the the power of styles (an area were WPF really shines imho) in order to set it for all elements to which a style is applied.


 <Style TargetType="TextBox">
        <Setter Property="myNamespace:MyBehavior.IsEnabled" Value="true" />
 </Style>

Personally I very much vote for the second option, because it enables you to specify the attached behavior in a single place in contrast to configuring it at several places in your solution. Don’t repeat yourself, unless you really need to.

Now, fasten your seatbelts. This is were the fun begins. When the WPF / Silverlight infrastructure loads the compiled baml from the resources and builds the element tree from it (and with this attaches our new property to the specified elements) the callback method gets called.


        private static void OnBehaviorEnabled(
            DependencyObject dependencyObject,
            DependencyPropertyChangedEventArgs args)
        {
            TextBox textBox = (TextBox)dependencyObject;

            textBox.LostFocus += (s,e) =>
            {
	          //Put your little piece of magic here
            };

        }
    }

With first parameter of the callback you get a reference to the DependencyObject to which our attached property has been attached to. You’re now able to wire all sort of event handlers to the DependencyObject and are able to execute arbitrary code when the event occurs.

Here ends our journey for today. Attached Behaviors is a really nice technique which enabled me to do something that I always wanted to have in my WinForms apps but never found a satisfiing way to implement it (just a bit patience, I’m going to blog about it soon). I think it will be interesting to see
how this pattern is used in the future. While new patterns always have the tendency to be overused, I think that this particular pattern can enable lots of valuable things . . .

Kick it on dotnet-kicks.de Kick it on DotNetKicks.com
BjRo posted at 2009-8-19 Category: WPF | Tags:

10 Responses Leave a comment

  1. #1Michael @ 2009-8-19 15:24

    Hey Bjoern,

    Clear and nice post. I completly agree with you and believe that people should really think twice before using new patterns all around.

    I am also really surprised by the clumsiness of the static constructor and the magic strings like “IsEnabled” cluttering the code. Actually really bad for refactoring.

    Eager to see your Winform example.

    Cheers,

  2. #2admin @ 2009-8-19 18:58

    Hi Michael,

    first of all thank you. The magic string is something which I don’t like, too. However you can easily wrap DependencyObject.RegisterAttached with an own method which uses Expressions in order to deptermine the propertys name (ala AttachedProperty.For(x => x.IsEnabled)). This might help. On the example side I hope I don’t disappoint you when I say the example isn’t actually WinForms it’s WPF …

    Cheers,
    Björn

  3. #3Hubert @ 2009-8-25 06:20

    Hey Björn,

    Firstly I gotta admit… you have made the Attached Behavior a lot clearer to me now :) … Thanks for that..

    However, I’m a bit lost by this :

    textBox.LostFocus += (s,e) =>
    {
    //Put your little piece of magic here
    };

    What exactly do you mean by (s,e) ?? I’m quite fresh with WPF and I’m hoping to gain a deeper insight of how I use this Attached Behavior to MVVM…

    Thanks again :)

  4. #4BjRo @ 2009-8-25 21:16

    Hi Hubert,

    this is just an anonymous event handler specified via a Lamda Expression. I’m a bit lazy, sorry. I guess it would have been more obvious if I had written (sender, args) out. Think of it as just some Delegate you can attach to the LostFocus event here . . .

    HTH,
    Björn

  5. #5Arch @ 2009-9-9 18:53

    Hi Björn – Thank you for the clear, concise example. I tried using this from Silverlight 3. Since there is no FrameworkPropertyMetadata in SL3 I tried replacing it with PropertyMetadata. This compiles fine but I get the error “The attachable property ‘IsEnabled’ was not found in type ‘MyBehavior’. Any work around for this?

    Thanks,
    AV

  6. #6Arch @ 2009-9-9 21:02

    Ok – found a solution for my above SL3 problem. Hope this helps other folks who are running into the same issue.

    Replace…

    public bool IsEnabled
    {
    get { return (bool)GetValue(IsEnabledProperty); }
    set { SetValue(IsEnabledProperty, value); }
    }

    With…

    public static void SetIsEnabled(DependencyObject obj, bool isEnabled)
    {
    obj.SetValue(IsEnabledProperty, isEnabled);
    }

    public static bool GetIsEnabled(DependencyObject ob)
    {
    return (bool)obj.GetValue(IsEnabledProperty);
    }

  7. #7BjRo @ 2009-9-9 21:54

    Hey AV,

    thanks for letting me know.

    To be honest I havent’t written anything in SL yet, only checked it in WPF. After reading your comment checked it again. Works in our WPF app.

    Seems to me that there some differences in how the Dependency Property system behaves in those two technologies. Wasn’t aware of that . . .

    Cheers,
    Björn

  8. #8Andres Olivares @ 2010-4-30 16:46

    Bjoern,

    Thanks for explaining this. I have done something like this when first using WPF in 2007 but I did not knw it was being considered a pattern. I agree with you, very calmly, it is a hack. In my implementation I did this for layouts, but not for measure and arrange, but to assign a child to the layout parent in a property it did not have. Yes a hack, but this is just an obvious hack.

    Thanks again.

    Andres

  9. #9Celina Torrie @ 2010-5-7 22:00

    I must say that your current blog site is completely informative. I have been investing a ton of effort in the last couple months searching at just what is on the market based on the actual fact that I’m arranging to launch a blogging site. The specifics you have place on here is nearly to the point. It just feels so difficult to understand related to all the technologies that are out there, but I enjoy the way your feels. Gotta absolutely adore where modern technology has come throughout the last twelve yrs.

  10. #10Mark Smeltzer @ 2010-7-28 03:49

    I recently ran into the same problem and I posted on my blog (http://www.livingagile.com/Blog/July-2010/Attaching-Behaviors-from-the-Expression-Blend-SDK-) on how to create a generic purpose attached property that will allow assigning any behaviors using a style.

Leave a Reply

(Ctrl + Enter)