Elad’s WPF Blog

April 2, 2009

Attached Behavior

Filed under: Programming, WPF — Tags: , , — Elad Malki @ 8:04 am

WPF has a powerful concept of Attached Properties. Since a Dependency Object is a kind of a sophisticated property bag, it can contain its own properties and other properties. The traditional use of attached properties is by the object that declare it, for example, A grid has a Row and a Column attached properties. It looks up these properties on every child of his, and use their values to arrange the children:

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition/>
    <RowDefinition/>
  </Grid.RowDefinitions>
  <Button Grid.Row="0">Button 1</Button>
  <Button Grid.Row="1">Button 2</Button>
</Grid>

A more advanced way of using attached properties is Attached Behaviors. An attached behavior is a way of extending or adding functionality of a dependency object (you can find more about it in Josh Smith’s article). For example, we might have a scenario in which we want to select the text of a TextBox when it gets the focus. A solution for this scenario could be hooking to the appropriate events in the code behind \ ViewModel of the TextBox and selecting the text when needed. There are two problems with this solution:

1. It requires writing code in an "inappropriate" WPF places such as code behind (which is always better to leave empty) or a ViewModel (which should contain info and logic of the view rather than technical stuff).

2. It requires writing a lot of code many times if we have more than one textbox, or several textboxes in different windows that needs this behavior.

A better solution would be writing an attached behavior. An attached behavior in WPF is normally a static class with one or more attached properties. The trick in this class is to listen to the change event of one of the properties, and to act upon it. This is an example of the Textbox "text selection on focus" behavior (Based on Eric Burke’s Post):

public static class SelectAllOnFocusBehaviour
{
        /// 1. This is the boolean attached property with its getter and setter:
        public static readonly DependencyProperty SelectAllOnFocusProperty =
            DependencyProperty.RegisterAttached
            (
                "SelectAllOnFocus",
                typeof(bool),
                typeof(SelectAllOnFocusBehaviour),
                new UIPropertyMetadata(false, OnSelectAllOnFocusPropertyChanged)
            );
        public static bool GetSelectAllOnFocus(DependencyObject obj)
        {
            return (bool)obj.GetValue(SelectAllOnFocusProperty);
        }
        public static void SetSelectAllOnFocus(DependencyObject obj, bool value)
        {
            obj.SetValue(SelectAllOnFocusProperty, value);
        }

        /// 2. This is the change event of our attached property value:
        ///     * We get in the first parameter the dependency object to which the attached behavior was attached
        ///     * We get in the second parameter the value of the attached behavior.
        ///     * The implementation of the behavior is to check if we are attached to a textBox, and if so and the value of the behavior
        ///       is true, hook to the PreviewGotKeyboardFocus of the textbox.
        private static void OnSelectAllOnFocusPropertyChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs args)
        {
            TextBoxBase textBox = dpo as TextBoxBase;
            if (textBox != null)
            {
                TextBoxBase tbb = dpo as TextBoxBase;
                if ((bool)args.NewValue)
                {
                    textBox.PreviewGotKeyboardFocus += OnTextBoxPreviewGotKeyboardFocus;
                }
                else
                {
                    textBox.PreviewGotKeyboardFocus -= OnTextBoxPreviewGotKeyboardFocus;
                }
            }
        }

        /// 3. The actual implementation: Whenever the textbox gets the keyboard focus, we select its text
        private static void OnTextBoxPreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            TextBoxBase txtBox = (TextBoxBase)sender;
            Action action = () => { txtBox.SelectAll(); };
            txtBox.Dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle);
        }
    }

And this is an example of the behavior usage:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:behaviors="your behavior xmlns path">
  <Grid>
    <TextBox Text="Some Text" behaviors:SelectAllOnFocusBehaviour.SelectAllOnFocus="True"/>
  </Grid>
</Page>

The result is a much declarative, maintainable and shorter code. You can find many useful behaviors on the web.

In Silverlight 3.0 there is a built in behaviors infrastructure, by using the Behaviors (and\or Triggers) attached property which contains a collection of behaviors (or Triggers).

Elad.

9 Comments »

  1. […] Filed under: Uncategorized — emalki @ 4:50 pm After talking about Attached Behavior in the last post, this is an example of a behavior which adds an animated GIF support to regular WPF Image […]

    Pingback by Animated GIF Support Behavior « Elad’s WPF Blog — April 2, 2009 @ 4:52 pm

  2. Nice sample. It’s a great example of an attached behavior.

    Comment by peteohanlon — May 7, 2009 @ 12:16 pm

    • Thanks 🙂

      Comment by Elad Malki — May 9, 2009 @ 9:24 pm

  3. Thanks. About the most simple and informative sample I’ve found. Great stuff. Cheers David

    Comment by DavidC — June 8, 2009 @ 4:35 pm

  4. Excuse me for writing offtopic – which WordPress template are you using? It’s looking cool!

    Comment by drudgenet — January 2, 2010 @ 2:54 am

    • Shocking Blue Green by Chris M

      Comment by Elad Malki — January 3, 2010 @ 2:49 pm

  5. woohoo thanks

    Comment by jan — February 17, 2010 @ 10:15 pm

  6. Awesome – thanks.

    Comment by Mr. BizTalk — January 12, 2012 @ 8:06 pm


RSS feed for comments on this post. TrackBack URI

Leave a reply to peteohanlon Cancel reply

Blog at WordPress.com.