Dutton

How to select all WPF TextBox text on focus using an Attached Behavior

UPDATE 12/11/2013: Fixed a mistake in the example code; the setter and getter shouldn't have "Property" in the name.

I have a simple requirement to select all of the text in a WPF TextBox when it receives focus, this lets a user tab through a bunch of TextBoxes and edit the values directly without having to use the mouse.

Although there are a few methods I could use, I thought I'd tackle this using the "Ramora", or "Attached Behavior" pattern. I always forget the syntax, hence this post.

Implementing an Attached Behavior involves creating a boolean Attached Property to indicate whether the behavior is to be applied, and then implementing the behavior in the property's change handler, like this:

    public class TextBoxBehavior
    {
        public static bool GetSelectAllTextOnFocus(TextBox textBox)
        {
            return (bool)textBox.GetValue(SelectAllTextOnFocusProperty);
        }

        public static void SetSelectAllTextOnFocus(TextBox textBox, bool value)
        {
            textBox.SetValue(SelectAllTextOnFocusProperty, value);
        }

        public static readonly DependencyProperty SelectAllTextOnFocusProperty =
            DependencyProperty.RegisterAttached(
                "SelectAllTextOnFocus",
                typeof (bool),
                typeof (TextBoxBehavior),
                new UIPropertyMetadata(false, OnSelectAllTextOnFocusChanged));

        private static void OnSelectAllTextOnFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var textBox = d as TextBox;
            if (textBox == null) return;

            if (e.NewValue is bool == false) return;

            if ((bool) e.NewValue)
            {
                textBox.GotFocus += SelectAll;
                textBox.PreviewMouseDown += IgnoreMouseButton;
            }
            else
            {
                textBox.GotFocus -= SelectAll;
                textBox.PreviewMouseDown -= IgnoreMouseButton;
            }
        }

        private static void SelectAll(object sender, RoutedEventArgs e)
        {
            var textBox = e.OriginalSource as TextBox;
            if (textBox == null) return;
            textBox.SelectAll();
        }

        private static void IgnoreMouseButton(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var textBox = sender as TextBox;
            if (textBox == null || textBox.IsKeyboardFocusWithin) return;

            e.Handled = true;
            textBox.Focus();
        }
    }

Which means you can use it like this in XAML:

<TextBox Text="Some Text" behaviors:TextBoxBehavior.SelectAllTextOnFocus="True"/>

So as you can see, it's really quite simple. I hook into the GotFocus event in `OnSelectAllTextOnFocusChanged`, and call `SelectAll` where I select all of the TextBox's text.

I added a further event handler to ensure that mouse clicks within the TextBox didn't highlight the text when it already had focus but this isn't essential.


Share this: