262

If I call SelectAll from a GotFocus event handler, it doesn't work with the mouse - the selection disappears as soon as mouse is released.

EDIT: People are liking Donnelle's answer, I'll try to explain why I did not like it as much as the accepted answer.

  • It is more complex, while the accepted answer does the same thing in a simpler way.
  • The usability of accepted answer is better. When you click in the middle of the text, text gets unselected when you release the mouse allowing you to start editing instantly, and if you still want to select all, just press the button again and this time it will not unselect on release. Following Donelle's recipe, if I click in the middle of text, I have to click second time to be able to edit. If I click somewhere within the text versus outside of the text, this most probably means I want to start editing instead of overwriting everything.
BigM
  • 678
  • 1
  • 17
  • 28
Sergey Aldoukhov
  • 22,316
  • 18
  • 72
  • 99
  • If you are going to have more than one form, her answer continues to become less complex than the first. Usability of both options is moot as you can change how either of them work. – thepaulpage Jun 09 '11 at 15:59
  • 1
    @Sergey: You may want to change the accepted answer for this question, as there have been better answers since. I'm not going to suggest mine, but you could ;) – Grokys Sep 02 '11 at 11:02
  • Question has Silverlight tag, yet Silverlight doesn't have most of events / any kind of preview events at all. Which solution should be used for silverlight then? – Valentin Kuzub Oct 05 '11 at 01:56
  • Link "Why is focus in WPF so tricky?" is broken – Maxence May 13 '14 at 07:29
  • 1
    as mentioned in a comment on http://stackoverflow.com/a/2553297/492 below, http://madprops.org/blog/wpf-textbox-selectall-on-focus/ is an easy solution and preserves the original nouse behaviour. I put the event registration in the constructor because I only have one WPF control in the app. – CAD bloke Apr 30 '15 at 02:28
  • http://stackoverflow.com/questions/31291770 – amit jha Aug 18 '15 at 10:57

35 Answers35

223

We have it so the first click selects all, and another click goes to cursor (our application is designed for use on tablets with pens).

You might find it useful.

public class ClickSelectTextBox : TextBox
{
    public ClickSelectTextBox()
    {
        AddHandler(PreviewMouseLeftButtonDownEvent, 
          new MouseButtonEventHandler(SelectivelyIgnoreMouseButton), true);
        AddHandler(GotKeyboardFocusEvent, 
          new RoutedEventHandler(SelectAllText), true);
        AddHandler(MouseDoubleClickEvent, 
          new RoutedEventHandler(SelectAllText), true);
    }

    private static void SelectivelyIgnoreMouseButton(object sender, 
                                                     MouseButtonEventArgs e)
    {
        // Find the TextBox
        DependencyObject parent = e.OriginalSource as UIElement;
        while (parent != null && !(parent is TextBox))
            parent = VisualTreeHelper.GetParent(parent);

        if (parent != null)
        {
            var textBox = (TextBox)parent;
            if (!textBox.IsKeyboardFocusWithin)
            {
                // If the text box is not yet focussed, give it the focus and
                // stop further processing of this click event.
                textBox.Focus();
                e.Handled = true;
            }
        }
    }

    private static void SelectAllText(object sender, RoutedEventArgs e)
    {
        var textBox = e.OriginalSource as TextBox;
        if (textBox != null)
            textBox.SelectAll();
    }
}
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
Donnelle
  • 5,689
  • 3
  • 27
  • 31
  • I have updated the question explaining why the selected answer is still better. – Sergey Aldoukhov Jul 07 '09 at 22:17
  • 6
    I saw a nearly identical answer here http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/564b5731-af8a-49bf-b297-6d179615819f/, it works as well, how ever it doesn't uses e.OriginalSource, nor crawls through the visual tree. Is there any advantage on doing all this? – Marco Luglio Jul 27 '09 at 03:01
  • 1
    Works great, but would be perfect if it still allowed drag-selection of text with the mouse. The Google Chrome address bar is a perfect example of the ideal system: if the user clicks and releases without dragging, the entire text is highlighted. However if the user clicks and drags, the drag selects text normally without selecting all. The SelectAll only occurs on mouse *release*. I will fiddle and see if I can improve this design at all. – devios1 Jun 02 '10 at 20:56
  • 2
    One further drawback of this solution is when you use the TextBox's "Cut/Copy/Paste" menu, the whole text is selected when you select any menu item. –  Sep 05 '12 at 13:32
  • 1
    I found that an additional test in the `SelectAllText` method of `textBox.IsFocused` improves it. You don't want to select all when the `GetKeyboardFocus` is due to alt-tabbing into the program. – Scott Stafford Apr 19 '14 at 01:40
  • I just wish there were better ways to modify how normal work without having to inherit and override in a subclass. – C. Tewalt Feb 18 '16 at 18:05
  • This breaks datagrid, when used in DataGridTemplateColumn without CellEditTemplate. Clicking on a textbox in a different datagrid row will not select that row anymore. The reason for this is the handling of the PreviewMouseDown event. Every other solution using this event, will have the same problem. – Welcor Feb 23 '20 at 18:47
180

Donnelle's answer works the best, but having to derive a new class to use it is a pain.

Instead of doing that I register handlers the handlers in App.xaml.cs for all TextBoxes in the application. This allows me to use a Donnelle's answer with standard TextBox control.

Add the following methods to your App.xaml.cs:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e) 
    {
        // Select the text in a TextBox when it receives focus.
        EventManager.RegisterClassHandler(typeof(TextBox), TextBox.PreviewMouseLeftButtonDownEvent,
            new MouseButtonEventHandler(SelectivelyIgnoreMouseButton));
        EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotKeyboardFocusEvent, 
            new RoutedEventHandler(SelectAllText));
        EventManager.RegisterClassHandler(typeof(TextBox), TextBox.MouseDoubleClickEvent,
            new RoutedEventHandler(SelectAllText));
        base.OnStartup(e); 
    }

    void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
    {
        // Find the TextBox
        DependencyObject parent = e.OriginalSource as UIElement;
        while (parent != null && !(parent is TextBox))
            parent = VisualTreeHelper.GetParent(parent);

        if (parent != null)
        {
            var textBox = (TextBox)parent;
            if (!textBox.IsKeyboardFocusWithin)
            {
                // If the text box is not yet focused, give it the focus and
                // stop further processing of this click event.
                textBox.Focus();
                e.Handled = true;
            }
        }
    }

    void SelectAllText(object sender, RoutedEventArgs e)
    {
        var textBox = e.OriginalSource as TextBox;
        if (textBox != null)
            textBox.SelectAll();
    }
}
Donnelle
  • 5,689
  • 3
  • 27
  • 31
Grokys
  • 16,228
  • 14
  • 69
  • 101
  • 4
    This is a pretty cool solution, it was also described by Matt Hamilton ages ago here: http://madprops.org/blog/wpf-textbox-selectall-on-focus/ – Ashley Davis Jul 07 '10 at 08:55
  • Question has Silverlight tag, yet Silverlight doesn't have most of events / any kind of preview events at all. Which solution should be used for silverlight then? thanks in advance – Valentin Kuzub Oct 05 '11 at 01:57
  • Best answer on the internet. – Sean Dec 14 '12 at 00:16
  • 2
    FAN - FREAKING - TASTIC. Thank you for this. I wish I could upvote this 255 times. – Steven C. Britton Sep 06 '14 at 12:31
  • 5
    "The spelling focused is much more common in the US; however, the spelling focussed is sometimes used in the UK and Canada, and is especially common in Australia and New Zealand." So nyah ;) – Donnelle Apr 22 '15 at 01:11
  • This is the best answer! – Etienne Charland May 27 '15 at 22:45
  • Just like @user128300 said about @Grokys?'s (currently Accepted) A above from "Mar 31 '10 at 13:32": "One further drawback of this solution is when you use the `TextBox`'s (default Context Menu, i.e.) `Cut`/`Copy`/`Paste` menu, the whole text is selected when you select any menu item.". I'd prefer not to have to use create/use a different `Class` in every app/for every `TextBox` Instance or worse, add Event Handlers every `TextBox` Instance, so this is my fav A. Any ideas how to avoid that drawback? – Tom Feb 20 '20 at 21:07
99

I have chosen part of Donnelle's answer (skipped the double-click) for I think this a more natural. However, like Grokys I dislike the need to create a derived class. But I also don't like Grokys' OnStartup method. And I need this on a "generally but not always" basis.

I have Implemented this as an attached DependencyProperty so I can set local:SelectTextOnFocus.Active = "True" in xaml. I find this way the most pleasing.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

public class SelectTextOnFocus : DependencyObject
{
    public static readonly DependencyProperty ActiveProperty = DependencyProperty.RegisterAttached(
        "Active",
        typeof(bool),
        typeof(SelectTextOnFocus),
        new PropertyMetadata(false, ActivePropertyChanged));

    private static void ActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is TextBox)
        {
            TextBox textBox = d as TextBox;
            if ((e.NewValue as bool?).GetValueOrDefault(false))
            {
                textBox.GotKeyboardFocus += OnKeyboardFocusSelectText;
                textBox.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
            }
            else
            {
                textBox.GotKeyboardFocus -= OnKeyboardFocusSelectText;
                textBox.PreviewMouseLeftButtonDown -= OnMouseLeftButtonDown;
            }
        }
    }

    private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        DependencyObject dependencyObject = GetParentFromVisualTree(e.OriginalSource);

        if (dependencyObject == null)
        {
            return;
        }

        var textBox = (TextBox)dependencyObject;
        if (!textBox.IsKeyboardFocusWithin)
        {
            textBox.Focus();
            e.Handled = true;
        }
    }

    private static DependencyObject GetParentFromVisualTree(object source)
    {
        DependencyObject parent = source as UIElement;
        while (parent != null && !(parent is TextBox))
        {
            parent = VisualTreeHelper.GetParent(parent);
        }

        return parent;
    }

    private static void OnKeyboardFocusSelectText(object sender, KeyboardFocusChangedEventArgs e)
    {
        TextBox textBox = e.OriginalSource as TextBox;
        if (textBox != null)
        {
            textBox.SelectAll();
        }
    }

    [AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(TextBox))]
    public static bool GetActive(DependencyObject @object)
    {
        return (bool) @object.GetValue(ActiveProperty);
    }

    public static void SetActive(DependencyObject @object, bool value)
    {
        @object.SetValue(ActiveProperty, value);
    }
}

For my "general but not always" feature I set this Attache Property to True in a (global) TextBox Style. This way "selecting the Text" is always "on", but I can disable it on a per-textbox-basis.

Clonkex
  • 3,373
  • 7
  • 38
  • 55
Nils
  • 9,682
  • 6
  • 46
  • 72
  • 9
    +1 this is much better than setting it globally, and it's more 'the WPF way' than deriving from TextBox. – stijn Apr 23 '12 at 14:01
  • 1
    Solid answer. Attached properties are very nice. – Vaccano May 11 '12 at 22:02
  • 3
    +1 Agree with stijn. "Hiding" your code in the app.cs is not nice for the poor dev who has to figure out why SelectAllOnFocus is happening. :-) I just dropped this into my class for TextBoxBehaviors and then updated my base TextBox Style. Worked a treat. Cheers – Lee Campbell Jun 13 '12 at 09:56
  • 1
    How do you add this in the Global TextBox style? – tronda Mar 05 '13 at 12:45
  • 2
    @tronda: Simply add a style to the resources using a TargetType of TextBox. I suggest you have a look at http://wpftutorial.net/Styles.html – Nils Mar 15 '13 at 16:49
  • I agree this is better than my answer! +1 – Grokys Sep 08 '14 at 12:43
  • 3
    Another +1 for the best answer. Only problem I find is that the text is always selected even when I use the right mouse button - which I frequently do to edit the text via context menu - the solution does not work for this case because it always selects all the text even if I just wanted to cut 1 word via context menu. Do you guys know how to fix this? – user3313608 Jul 19 '15 at 15:07
  • 2
    I like this answer but why do you have to extend DependencyObject? I removed that and it still works fine. – Fred Mar 23 '16 at 09:49
  • @Fred I agree - it is only necessary to derive from DependencyObject if you want ordinary DependencyProperties for that class, not to make attached properties that apply to other classes (which already must be derived from DependencyObject). Furthermore, the entire class could be static. – M Kloster Jan 11 '22 at 15:30
88

Don't know why it loses the selection in the GotFocus event.

But one solution is to do the selection on the GotKeyboardFocus and the GotMouseCapture events. That way it will always work.

-- Edit --

Adding an example here to show people how to work around some the mentioned drawbacks:

private void TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    // Fixes issue when clicking cut/copy/paste in context menu
    if (textBox.SelectionLength == 0) 
        textBox.SelectAll();
}

private void TextBox_LostMouseCapture(object sender, MouseEventArgs e)
{
    // If user highlights some text, don't override it
    if (textBox.SelectionLength == 0) 
        textBox.SelectAll();

    // further clicks will not select all
    textBox.LostMouseCapture -= TextBox_LostMouseCapture; 
}

private void TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    // once we've left the TextBox, return the select all behavior
    textBox.LostMouseCapture += TextBox_LostMouseCapture;
}
Ben Zuill-Smith
  • 3,504
  • 3
  • 25
  • 44
gcores
  • 12,376
  • 2
  • 49
  • 45
  • 12
    Nope. When clicked with the mouse in the middle of existing text - selection is lost as soon as mouse button is released. – Sergey Aldoukhov Mar 19 '09 at 02:12
  • 4
    Though - after a second single click, it selects all text again... Not sure if it is an intended behavior from WPF designers, but usability is not that bad. Another difference from a single GotFocus handler is that clicking on an empty space in the TextBox does select all. – Sergey Aldoukhov Mar 19 '09 at 03:25
  • 3
    This was my fist solution, too. But I found that users are really annoyed, when they're unable to select Text using the Mouse, because everytime they click the whole text gets selected... – Nils Apr 20 '10 at 10:37
  • 1
    One further drawback of this solution is when you use the TextBox's "Cut/Copy/Paste" menu, the whole text is selected when you select any menu item. –  Sep 05 '12 at 13:29
  • @gcores I know this is old, but does anyone know why in the GotFocus event the selected text is lost? You're right about it working in other events, though and that's a perfectly acceptable solution in my book. – Feign Apr 02 '15 at 19:51
  • Is there any solution? – Dominic Jonas Jan 18 '17 at 15:39
  • Using the `LostMouseCapture` event instead works for me... – tombobadil Dec 18 '20 at 15:26
43

Here are the Blend behaviors implementing the answer solution for your convenience:

One for attaching to a single TextBox:

public class SelectAllTextOnFocusBehavior : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.GotKeyboardFocus += AssociatedObjectGotKeyboardFocus;
        AssociatedObject.GotMouseCapture += AssociatedObjectGotMouseCapture;
        AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObjectPreviewMouseLeftButtonDown;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.GotKeyboardFocus -= AssociatedObjectGotKeyboardFocus;
        AssociatedObject.GotMouseCapture -= AssociatedObjectGotMouseCapture;
        AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObjectPreviewMouseLeftButtonDown;
    }

    private void AssociatedObjectGotKeyboardFocus(object sender,
        System.Windows.Input.KeyboardFocusChangedEventArgs e)
    {
        AssociatedObject.SelectAll();
    }

    private void AssociatedObjectGotMouseCapture(object sender,
        System.Windows.Input.MouseEventArgs e)
    {
        AssociatedObject.SelectAll();   
    }

    private void AssociatedObjectPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if(!AssociatedObject.IsKeyboardFocusWithin)
        {
            AssociatedObject.Focus();
            e.Handled = true;
        }
    }
}

And one for attaching to the root of a container containing multiple TextBox'es:

public class SelectAllTextOnFocusMultiBehavior : Behavior<UIElement>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.GotKeyboardFocus += HandleKeyboardFocus;
        AssociatedObject.GotMouseCapture += HandleMouseCapture;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.GotKeyboardFocus -= HandleKeyboardFocus;
        AssociatedObject.GotMouseCapture -= HandleMouseCapture;
    }

    private static void HandleKeyboardFocus(object sender,
        System.Windows.Input.KeyboardFocusChangedEventArgs e)
    {
        var txt = e.NewFocus as TextBox;
        if (txt != null)
            txt.SelectAll();
    }

    private static void HandleMouseCapture(object sender,
        System.Windows.Input.MouseEventArgs e)
    {
        var txt = e.OriginalSource as TextBox;
        if (txt != null)
            txt.SelectAll();
    }
}
Chords
  • 6,720
  • 2
  • 39
  • 61
Sergey Aldoukhov
  • 22,316
  • 18
  • 72
  • 99
  • This is by far the best and cleanest solution. Thanks a lot for sharing it. – Golvellius Jul 04 '13 at 08:00
  • It looks really nice, but for some reason it breaks tab control... Any idea why? – Marc Jul 26 '13 at 08:42
  • I'd like to use yor solution. But really lost... maybe do you have a sample? – Juan Pablo Gomez Jul 24 '14 at 15:49
  • When you click somewhere in the textbox while having focus (imagine you want to move caret to another place) it will SelectAll again instead of moving caret. It's unexpected. Fixed it by replacing GotMouseCapture with MouseDoubleClick which is common. Thanks to latter solutions from MSDN. – norekhov Sep 04 '14 at 14:33
  • 1
    It doesn't seem to work when the textbox receives initial focus via FocusManager.FocusedElement. Any ideas why? – szx Feb 24 '15 at 05:51
  • `SelectAllTextOnFocusBehavior` works perfect but `SelectAllTextOnFocusMultiBehavior` has the same issue as in the question. I tried to fix by adding the PreviewMouseLeftButtonDown but that isn't fired somehow... It's just selected correctly if you click behind the text and not in the text – KCT Jan 29 '16 at 08:22
33

I solved this problem using an Attached Behavior rather than an Expression Behavior as in Sergey's answer. This means I don't need a dependency on System.Windows.Interactivity in the Blend SDK:

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.IsReadOnly && textBox.IsKeyboardFocusWithin)) return;

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

You can then use it in your XAML like this:

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

I blogged about it here.

Dutts
  • 5,781
  • 3
  • 39
  • 61
  • I like this approach but the Get/Set methods shouldn't end in "Property"; I had to remove that to get the code compiling after adding the Xaml portion. – Patrick Quirk Nov 11 '13 at 20:35
  • Very nice, worked just as expected. I like this because it helps me keep View concerns separated when doing MVVM. – Killnine Oct 17 '14 at 13:29
  • 1
    The blog post link didn't work for me, this did http://www.dutton.me.uk/2013-07-25/how-to-select-all-wpf-textbox-text-on-focus-using-an-attached-behavior/ – Steve Jul 07 '21 at 15:37
  • Thanks @Steve, I've updated the URI in the answer – Dutts Jul 27 '21 at 09:21
17

Here's a very good very simple solution on MSDN:

<TextBox
    MouseDoubleClick="SelectAddress"
    GotKeyboardFocus="SelectAddress"
    PreviewMouseLeftButtonDown="SelectivelyIgnoreMouseButton" />

Here's the code behind:

private void SelectAddress(object sender, RoutedEventArgs e)
{
    TextBox tb = (sender as TextBox);
    if (tb != null)
    {
        tb.SelectAll();
    }
}

private void SelectivelyIgnoreMouseButton(object sender,
    MouseButtonEventArgs e)
{
    TextBox tb = (sender as TextBox);
    if (tb != null)
    {
        if (!tb.IsKeyboardFocusWithin)
        {
            e.Handled = true;
            tb.Focus();
        }
    }
}
GitaarLAB
  • 14,536
  • 11
  • 60
  • 80
BillBR
  • 169
  • 1
  • 2
  • 1
    Essentially, this is the same solution as the most rated one in this thread. But since it two years earlier, now I know where from @Donnelle borrowed it ;) – Sergey Aldoukhov May 02 '13 at 05:41
  • This solution seemed the easiest and worked for me. I wanted a specific subset of text selected by default when entering the textbox. – Jack B Nimble Feb 23 '16 at 14:57
12

I think this works well:

private void ValueText_GotFocus(object sender, RoutedEventArgs e)
{
    TextBox tb = (TextBox)e.OriginalSource;
    tb.Dispatcher.BeginInvoke(
        new Action(delegate
            {
                tb.SelectAll();
            }), System.Windows.Threading.DispatcherPriority.Input);
}

If you would like to implement it as an extension method:

public static void SelectAllText(this System.Windows.Controls.TextBox tb)
{
    tb.Dispatcher.BeginInvoke(
        new Action(delegate
        {
            tb.SelectAll();
        }), System.Windows.Threading.DispatcherPriority.Input);
}

And in your GotFocus event:

private void ValueText_GotFocus(object sender, RoutedEventArgs e)
{
    TextBox tb = (TextBox)e.OriginalSource;
    tb.SelectAllText();
}

I discovered the solution above because several months ago I was looking for a way to set focus to a given UIElement. I discovered the the code below somewhere (credit is hereby given) and it works well. I post it even though it is not directly related to the OP's question because it demonstrates the same pattern of using Dispatcher to work with a UIElement.

// Sets focus to uiElement
public static void DelayedFocus(this UIElement uiElement)
{
    uiElement.Dispatcher.BeginInvoke(
    new Action(delegate
    {
        uiElement.Focusable = true;
        uiElement.Focus();
        Keyboard.Focus(uiElement);
    }),
    DispatcherPriority.Render);
}
Sam
  • 1,621
  • 3
  • 22
  • 30
  • I guess this is the simplest method to implement. after creating the extension method you will just have to call myTextBox.SelectAllText() . Why is this answer not received more points? why are the other solutions so much better? – Tono Nam Mar 22 '12 at 04:40
  • 2
    I would avoid this method because it's relying on an async call to run after the textbox's MouseUp handler. I wouldn't trust this to be 100% deterministic, and may lead to inconsistent behavior. Even though it may be unlikely to occur, I would rather go with the surefire methods above. – Rob H Aug 21 '13 at 16:29
7

In App.xaml file:

<Application.Resources>
    <Style TargetType="TextBox">
        <EventSetter Event="GotKeyboardFocus" Handler="TextBox_GotKeyboardFocus"/>
    </Style>
</Application.Resources>

In App.xaml.cs file:

private void TextBox_GotKeyboardFocus(Object sender, KeyboardFocusChangedEventArgs e)
{
    ((TextBox)sender).SelectAll();
}

With this code you reach all TextBox in your application.

Darshan Faldu
  • 1,471
  • 2
  • 15
  • 32
6

This simple implementation works perfectly for me:

void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    ((TextBox) sender).SelectAll();
}

void TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    var TextBox = (TextBox) sender;
    if (!TextBox.IsKeyboardFocusWithin)
    {
        TextBox.Focus();
        e.Handled = true;
    }
}

To apply it to all TextBox's, put the following code after InitializeComponent();

EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotFocusEvent, new RoutedEventHandler(TextBox_GotFocus));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.PreviewMouseDownEvent, new MouseButtonEventHandler(TextBox_PreviewMouseDown));
Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
6

I've found none of the answers presented here mimic a standard Windows textbox. For instance, try to click in the white space between the last character of the textbox and the right side of the textbox. Most of the solutions here will always select the whole content, which makes it very difficult to append text to a textbox.

The answer that I present here behaves better in this respect. It is a behavior (so it requires the System.Windows.Interactivity assembly from the Blend SDK). It could be rewritten using attached properties as well.

public sealed class SelectAllTextOnFocusBehavior : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObject_PreviewMouseLeftButtonDown;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObject_PreviewMouseLeftButtonDown;
    }

    void AssociatedObject_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        // Find the textbox
        DependencyObject parent = e.OriginalSource as UIElement;
        while (parent != null && !(parent is TextBox))
            parent = VisualTreeHelper.GetParent(parent);

        var textBox = parent as TextBox;
        Debug.Assert(textBox != null);

        if (textBox.IsFocused) return;

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

This is based on code I've found here.

  • 1
    While this is a good answer, I think that when user clicks on the white space his intention (in a business application) is most probably to override the entire value, so selecting all is the right approach. – Sergey Aldoukhov Jul 27 '10 at 18:18
  • 1
    Sergey: the first click will select the entire value, the second click will put the cursor at the right of the value. In the other presented solutions, the second click will keep the entire value selected, making it very difficult to append to the value. – Kristof Verbiest Jul 30 '10 at 11:36
  • How is this used? I added this code to App.xaml.cs but it didn't seem to have an effect on the TextBoxes in my app. – PIntag Dec 16 '11 at 22:50
5

I have used Nils' answer but converted to more flexible.

public enum SelectAllMode
{

    /// <summary>
    ///  On first focus, it selects all then leave off textbox and doesn't check again
    /// </summary>
    OnFirstFocusThenLeaveOff = 0,

    /// <summary>
    ///  On first focus, it selects all then never selects
    /// </summary>
    OnFirstFocusThenNever = 1,

    /// <summary>
    /// Selects all on every focus
    /// </summary>
    OnEveryFocus = 2,

    /// <summary>
    /// Never selects text (WPF's default attitude)
    /// </summary>
    Never = 4,
}

public partial class TextBox : DependencyObject
{
    public static readonly DependencyProperty SelectAllModeProperty = DependencyProperty.RegisterAttached(
        "SelectAllMode",
        typeof(SelectAllMode?),
        typeof(TextBox),
        new PropertyMetadata(SelectAllModePropertyChanged));

    private static void SelectAllModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is System.Windows.Controls.TextBox)
        {
            var textBox = d as System.Windows.Controls.TextBox;

            if (e.NewValue != null)
            {
                textBox.GotKeyboardFocus += OnKeyboardFocusSelectText;
                textBox.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
            }
            else
            {
                textBox.GotKeyboardFocus -= OnKeyboardFocusSelectText;
                textBox.PreviewMouseLeftButtonDown -= OnMouseLeftButtonDown;
            }
        }
    }

    private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        DependencyObject dependencyObject = GetParentFromVisualTree(e.OriginalSource);

        if (dependencyObject == null)
            return;

        var textBox = (System.Windows.Controls.TextBox)dependencyObject;
        if (!textBox.IsKeyboardFocusWithin)
        {
            textBox.Focus();
            e.Handled = true;
        }
    }

    private static DependencyObject GetParentFromVisualTree(object source)
    {
        DependencyObject parent = source as UIElement;
        while (parent != null && !(parent is System.Windows.Controls.TextBox))
        {
            parent = VisualTreeHelper.GetParent(parent);
        }

        return parent;
    }

    private static void OnKeyboardFocusSelectText(object sender, KeyboardFocusChangedEventArgs e)
    {
        var textBox = e.OriginalSource as System.Windows.Controls.TextBox;
        if (textBox == null) return;

        var selectAllMode = GetSelectAllMode(textBox);

        if (selectAllMode == SelectAllMode.Never)
        {
            textBox.SelectionStart = 0;
            textBox.SelectionLength = 0;
        }
        else
            textBox.SelectAll();

        if (selectAllMode == SelectAllMode.OnFirstFocusThenNever)
            SetSelectAllMode(textBox, SelectAllMode.Never);
        else if (selectAllMode == SelectAllMode.OnFirstFocusThenLeaveOff)
            SetSelectAllMode(textBox, null);
    }

    [AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(System.Windows.Controls.TextBox))]
    public static SelectAllMode? GetSelectAllMode(DependencyObject @object)
    {
        return (SelectAllMode)@object.GetValue(SelectAllModeProperty);
    }

    public static void SetSelectAllMode(DependencyObject @object, SelectAllMode? value)
    {
        @object.SetValue(SelectAllModeProperty, value);
    }
}

In XAML, you can use like one of these:

<!-- On first focus, it selects all then leave off textbox and doesn't check again -->
<TextBox attprop:TextBox.SelectAllMode="OnFirstFocusThenLeaveOff" />

<!-- On first focus, it selects all then never selects -->
<TextBox attprop:TextBox.SelectAllMode="OnFirstFocusThenNever" />

<!-- Selects all on every focus -->
<TextBox attprop:TextBox.SelectAllMode="OnEveryFocus" />

<!-- Never selects text (WPF's default attitude) -->
<TextBox attprop:TextBox.SelectAllMode="Never" />
bafsar
  • 1,080
  • 2
  • 16
  • 16
  • 2
    Really good solution for use in templates since you can bind it to xaml without any actual codebehind, just extended behaviour of the textbox. – Eric Johansson Feb 06 '20 at 14:59
4

Taken from here:

Register global event handler in App.xaml.cs file:

protected override void OnStartup(StartupEventArgs e)
{
    EventManager.RegisterClassHandler(typeof(TextBox),TextBox.GotFocusEvent,
    new RoutedEventHandler(TextBox_GotFocus));

    base.OnStartup(e);
}

Then the handler is as simple as:

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    (sender as TextBox).SelectAll();
}
Neomoon
  • 181
  • 1
  • 3
  • 12
  • This way it also affects multi-line text fields, which should come as quite a surprise to Windows-experienced users. – Wolf Mar 15 '22 at 13:21
4

I have a slightly simplified answer for this (with just the PreviewMouseLeftButtonDown event) which seems to mimic the usual functionality of a browser:

In XAML you have a TextBox say:

<TextBox Text="http://www.blabla.com" BorderThickness="2" BorderBrush="Green" VerticalAlignment="Center" Height="25"
                 PreviewMouseLeftButtonDown="SelectAll" />

In codebehind:

private void SelectAll(object sender, MouseButtonEventArgs e)
{
    TextBox tb = (sender as TextBox);

    if (tb == null)
    {
        return;
    }

    if (!tb.IsKeyboardFocusWithin)
    {
        tb.SelectAll();
        e.Handled = true;
        tb.Focus();
    }
}
Danield
  • 121,619
  • 37
  • 226
  • 255
  • 1
    Might want to add a GotKeyboardFocus event with TextBox.SelectAll() inside for people who tab their way around your application. Your solution works for PasswordBoxes too (since PasswordBoxes are sealed types they cannot be extended). – David Sherret Jun 29 '12 at 19:58
3

I realize this is very old, but here is my solution which is based on the expressions/microsoft interactivity and interactions name spaces.

First, I followed the instructions at this link to place interactivity triggers into a style.

Then it comes down to this

<Style x:Key="baseTextBox" TargetType="TextBox">
  <Setter Property="gint:InteractivityItems.Template">
    <Setter.Value>
      <gint:InteractivityTemplate>
        <gint:InteractivityItems>
          <gint:InteractivityItems.Triggers>
            <i:EventTrigger EventName="GotKeyboardFocus">
              <ei:CallMethodAction MethodName="SelectAll"/>
            </i:EventTrigger>
            <i:EventTrigger EventName="PreviewMouseLeftButtonDown">
              <ei:CallMethodAction MethodName="TextBox_PreviewMouseLeftButtonDown"
                TargetObject="{Binding ElementName=HostElementName}"/>
            </i:EventTrigger>
          </gint:InteractivityItems.Triggers>
        </gint:InteractivityItems>
      </gint:InteractivityTemplate>
    </Setter.Value>
  </Setter>
</Style>

and this

public void TextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
  TextBox tb = e.Source as TextBox;
  if((tb != null) && (tb.IsKeyboardFocusWithin == false))
  {
    tb.Focus();
    e.Handled = true;
  }
}

In my case, I have a user control where the text boxes are that has a code-behind. The code-behind has the handler function. I gave my user control a name in XAML, and I am using that name for the element. This is working perfectly for me. Simply apply the style to any TextBox where you would like to have all the text selected when you click in the TextBox.

The first CallMethodAction calls the text box's SelectAll method when the GotKeyboardFocus event on the TextBox fires.

I hope this helps.

wiyosaya
  • 95
  • 9
  • Since this is such an old questions, it might help your answer get some attention if you mention why someone might choose this approach. – divibisan Mar 26 '18 at 21:50
  • First off, this does not need to be put in a style, but I think it obvious that there are many text box controls that need this, a style is the way to go. – wiyosaya Mar 28 '18 at 15:41
  • 1
    Maybe some will not agree with this approach, however, as to why you might use this approach, it does not require subclassing TextBox, registering class handler events, extension methods, creating attached properties, etc. As a style, it could also be added to the resource dictionary of any xaml project. Without the x:Key, it would be applied to any TextBox instance within the scope of the resource dictionary without having to alter the xaml of each individual text box. In some cases, it may be a cleaner approach. – wiyosaya Mar 28 '18 at 16:04
3

Here is an attempt to solve some of the problems with other solutions:

  1. Using right click context menu for cut/copy/past selects all text even if you didn't select it all.
  2. When returning from right click context menu, all text is always selected.
  3. When returning to the application with Alt+Tab, all text is always selected.
  4. When trying to select only part of the text on the first click, all is always selected (unlike Google chromes address bar for example).

The code I wrote is configurable. You can choose on what actions the select all behavior should occur by setting three readonly fields: SelectOnKeybourdFocus, SelectOnMouseLeftClick, SelectOnMouseRightClick.

The downside of this solution is that it's more complex and static state is stored. Its seems like an ugly struggle with the defaults behavior of the TextBox control. Still, it works and all the code is hidden in the Attached Property container class.

public static class TextBoxExtensions
{
    // Configuration fields to choose on what actions the select all behavior should occur.
    static readonly bool SelectOnKeybourdFocus = true;
    static readonly bool SelectOnMouseLeftClick = true;
    static readonly bool SelectOnMouseRightClick = true;

    // Remembers a right click context menu that is opened 
    static ContextMenu ContextMenu = null;

    // Remembers if the first action on the TextBox is mouse down 
    static bool FirstActionIsMouseDown = false;

    public static readonly DependencyProperty SelectOnFocusProperty =
        DependencyProperty.RegisterAttached("SelectOnFocus", typeof(bool), typeof(TextBoxExtensions), new PropertyMetadata(false, new PropertyChangedCallback(OnSelectOnFocusChanged)));

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(TextBox))]
    public static bool GetSelectOnFocus(DependencyObject obj)
    {
        return (bool)obj.GetValue(SelectOnFocusProperty);
    }

    public static void SetSelectOnFocus(DependencyObject obj, bool value)
    {
        obj.SetValue(SelectOnFocusProperty, value);
    }

    private static void OnSelectOnFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (!(d is TextBox textBox)) return;

        if (GetSelectOnFocus(textBox))
        {
            // Register events
            textBox.PreviewMouseDown += TextBox_PreviewMouseDown;
            textBox.PreviewMouseUp += TextBox_PreviewMouseUp;
            textBox.GotKeyboardFocus += TextBox_GotKeyboardFocus;
            textBox.LostKeyboardFocus += TextBox_LostKeyboardFocus;
        }
        else
        {
            // Unregister events
            textBox.PreviewMouseDown -= TextBox_PreviewMouseDown;
            textBox.PreviewMouseUp -= TextBox_PreviewMouseUp;
            textBox.GotKeyboardFocus -= TextBox_GotKeyboardFocus;
            textBox.LostKeyboardFocus -= TextBox_LostKeyboardFocus;
        }
    }

    private static void TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        if (!(sender is TextBox textBox)) return;

        // If mouse clicked and focus was not in text box, remember this is the first click.
        // This will enable to prevent select all when the text box gets the keyboard focus 
        // right after the mouse down event.
        if (!textBox.IsKeyboardFocusWithin)
        {
            FirstActionIsMouseDown = true;
        }
    }

    private static void TextBox_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        if (!(sender is TextBox textBox)) return;

        // Select all only if:
        // 1) SelectOnMouseLeftClick/SelectOnMouseRightClick is true and left/right button was clicked
        // 3) This is the first click
        // 4) No text is selected
        if (((SelectOnMouseLeftClick && e.ChangedButton == MouseButton.Left) || 
            (SelectOnMouseRightClick && e.ChangedButton == MouseButton.Right)) &&
            FirstActionIsMouseDown &&
            string.IsNullOrEmpty(textBox.SelectedText))
        {
            textBox.SelectAll();
        }

        // It is not the first click 
        FirstActionIsMouseDown = false;
    }

    private static void TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        if (!(sender is TextBox textBox)) return;

        // Select all only if:
        // 1) SelectOnKeybourdFocus is true
        // 2) Focus was not previously out of the application (e.OldFocus != null)
        // 3) The mouse was pressed down for the first after on the text box
        // 4) Focus was not previously in the context menu
        if (SelectOnKeybourdFocus &&
            e.OldFocus != null &&
            !FirstActionIsMouseDown &&
            !IsObjectInObjectTree(e.OldFocus as DependencyObject, ContextMenu))
        {
            textBox.SelectAll();
        }

        // Forget ContextMenu
        ContextMenu = null;
    }

    private static void TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        if (!(sender is TextBox textBox)) return;

        // Remember ContextMenu (if opened)
        ContextMenu = e.NewFocus as ContextMenu;

        // Forget selection when focus is lost if:
        // 1) Focus is still in the application
        // 2) The context menu was not opened
        if (e.NewFocus != null
            && ContextMenu == null)
        {
            textBox.SelectionLength = 0;
        }
    }

    // Helper function to look if a DependencyObject is contained in the visual tree of another object
    private static bool IsObjectInObjectTree(DependencyObject searchInObject, DependencyObject compireToObject)
    {
        while (searchInObject != null && searchInObject != compireToObject)
        {
            searchInObject = VisualTreeHelper.GetParent(searchInObject);
        }

        return searchInObject != null;
    }
}

To attache the Attached Property to a TextBox, all you need to do is add the xml namespace (xmlns) of the Attached Property and then use it like this:

<TextBox attachedprop:TextBoxExtensions.SelectOnFocus="True"/>

Some notes about this solution:

  1. To override the default behavior of a mouse down event and enable selecting only part of the text on the first click, all text is selected on mouse up event.
  2. I had to deal with the fact the the TextBox remembers its selection after it loses focus. I actually have overridden this behavior.
  3. I had to remember if a mouse button down is the first action on the TextBox (FirstActionIsMouseDown static field).
  4. I had to remember the context menu opened by a right click (ContextMenu static field).

The only side effect I found is when SelectOnMouseRightClick is true. Sometimes the right-click context menu flickers when its opened and right-clicking on a blank are in the TextBox does not do "select all".

Eliahu Aaron
  • 4,103
  • 5
  • 27
  • 37
2

After googling and testing, I've found a simple solution that worked for me.

You need to add an event handler to the Loaded event of your container window:

private void yourwindow_Loaded(object sender, RoutedEventArgs e)
{
    EventManager.RegisterClassHandler(typeof(TextBox),
        TextBox.PreviewMouseLeftButtonDownEvent,
        new RoutedEventHandler(SelectivelyIgnoreMouseButton));
}

Next, you have to create the handler to the referenced RoutedEventHandler in previous code:

private void SelectivelyIgnoreMouseButton(object sender, RoutedEventArgs e)
{
    TextBox tb = (sender as TextBox);
    if (tb != null)
    {
        if (!tb.IsKeyboardFocusWithin)
        {
            e.Handled = true;
            tb.Focus();
        }
    }
}

Now, you can add the SelectAll() command on GotFocus event handlers to any TextBox controls separately:

private void myTextBox_GotFocus(object sender, RoutedEventArgs e)
{
    (sender as TextBox).SelectAll();
}

Your text now is selected on focus!

Adapted from Dr. WPF solution, MSDN Forums

DonBeto97
  • 31
  • 1
  • I just used: private async void TBTime_GotFocus(object sender, RoutedEventArgs e) { TextBox tb = (TextBox)e.OriginalSource; await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => { tb.SelectAll(); }); } – David Jones Apr 29 '18 at 11:15
2

This is by far the most straightforward solution I found.

You are going to need only a few lines of code.

Add a global handler to the application (App.xaml.cs). Use the EventManager class to register a global event handler against a type, in this case, the TextBox.

protected override void OnStartup(StartupEventArgs e)
{
    EventManager.RegisterClassHandler(typeof(TextBox),
        TextBox.GotFocusEvent,
        new RoutedEventHandler(TextBox_GotFocus));

    base.OnStartup(e);
}

Then use the event handler to select all the Textbox contents.

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    (sender as TextBox).SelectAll();
}

Check here: WPF TextBox SelectAll on Focus

I hope it helps.

Marlon Assef
  • 1,441
  • 15
  • 18
  • The automatic selection also affects multi-line text fields, which should come as quite a surprise to Windows-experienced users. But a good starting point. – Wolf Mar 15 '22 at 13:19
2

Here is the C# version of the answer posted by @Nasenbaer

private delegate void TextBoxSelectAllDelegate(object sender);

private void TextBoxSelectAll(object sender)
{
    (sender as System.Windows.Controls.TextBox).SelectAll();
}

private void MyTextBox_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
    TextBoxSelectAllDelegate d = TextBoxSelectAll;

    this.Dispatcher.BeginInvoke(d,
        System.Windows.Threading.DispatcherPriority.ApplicationIdle, sender);
}

whereas MyTextBox_GotFocus is the event handler assigned to the GotFocus event of MyTextBox.

ViRuSTriNiTy
  • 5,017
  • 2
  • 32
  • 58
1

I had same problem. In VB.Net it works easy that way:

VB XAML:

<TextBox x:Name="txtFilterFrequency" />

Codehind:

Private Sub txtFilterText_GotFocus(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles txtFilterText.GotFocus
    Me.Dispatcher.BeginInvoke(Sub()
                                  txtFilterText.SelectAll()
                              End Sub, DispatcherPriority.ApplicationIdle, Nothing)
End Sub

C# (thanks to ViRuSTriNiTy)

private delegate void TextBoxSelectAllDelegate(object sender);

private void TextBoxSelectAll(object sender)
{
    (sender as System.Windows.Controls.TextBox).SelectAll();
}

private void MyTextBox_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
    TextBoxSelectAllDelegate d = TextBoxSelectAll;

    this.Dispatcher.BeginInvoke(d,
        System.Windows.Threading.DispatcherPriority.ApplicationIdle, sender);
}
Nasenbaer
  • 4,810
  • 11
  • 53
  • 86
  • Best solution for me, i've posted a C# translation here: https://stackoverflow.com/a/48385409/3936440 – ViRuSTriNiTy Jan 22 '18 at 15:49
  • For me, this approach occasionally fails to select text. I think it's race condition due to BeginInvoke. – Vimes May 06 '20 at 20:49
  • Please specify. The dispatcher priority is working on default applications as expected. What is your situation? Did you try exact as described? Anything special in your solution? – Nasenbaer Jun 06 '20 at 19:09
1

I searched a lot for the solution, I found couple of solutions to selectall But, the issue is when we do right click and do cut/copy after selecting part of text from text box, it selects all even I selected part of text. To fix this here is the solution. Just add the below code in the keyboard select event. This worked for me.

private static void SelectContentsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (d is TextBox)
    {
        TextBox textBox = d as TextBox;
        if ((e.NewValue as bool?).GetValueOrDefault(false))
        {
            textBox.GotKeyboardFocus += OnKeyboardFocusSelectText;                 
        }
        else
        {
            textBox.GotKeyboardFocus -= OnKeyboardFocusSelectText;

        }
    }
}


private static void OnKeyboardFocusSelectText(object sender, KeyboardFocusChangedEventArgs e)
{
    if (e.KeyboardDevice.IsKeyDown(Key.Tab))
        ((TextBox)sender).SelectAll();
}
1

For those interested in Donnelle's/Groky's approach, but want a click to the right of the last character (but still within the TextBox) to place the caret at the end of the entered text, I've come up with this solution:

int GetRoundedCharacterIndexFromPoint(TextBox textBox, Point clickedPoint)
{
    int position = textBox.GetCharacterIndexFromPoint(clickedPoint, true);

    // Check if the clicked point is actually closer to the next character
    // or if it exceeds the righmost character in the textbox
    // (in this case return increase the position by 1)
    Rect charLeftEdge = textBox.GetRectFromCharacterIndex(position, false);
    Rect charRightEdge = textBox.GetRectFromCharacterIndex(position, true);
    double charWidth = charRightEdge.X - charLeftEdge.X;
    if (clickedPoint.X + charWidth / 2 > charLeftEdge.X + charWidth) position++;

    return position;
}

void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
{
    // Find the TextBox
    DependencyObject parent = e.OriginalSource as UIElement;
    while (parent != null && !(parent is TextBox))
        parent = VisualTreeHelper.GetParent(parent);

    if (parent != null)
    {
        var textBox = (TextBox)parent;
        if (!textBox.IsKeyboardFocusWithin)
        {
            // If the text box is not yet focused, give it the focus and
            // stop further processing of this click event.
            textBox.Focus();
            e.Handled = true;
        }
        else
        {
            int pos = GetRoundedCharacterIndexFromPoint(textBox, e.GetPosition(textBox));
            textBox.CaretIndex = pos;
        }
    }
}

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

The GetRoundedCharacterIndexFromPoint method was taken from this post.

PIntag
  • 932
  • 11
  • 26
  • 1
    Works fine, but the double click event doesn't get triggered – Rodrigo Caballero Mar 18 '14 at 14:36
  • Actually it does enter to the doubleclick event but the OriginalSource property is of type TextBoxView. So the SelectAllText method should be like this: private static void SelectAllText(object sender, RoutedEventArgs e) { var textBox = e.OriginalSource as TextBox; if (textBox != null) { textBox.SelectAll(); System.Diagnostics.Debug.WriteLine(" Selected ALL "); } else if (sender is TextBox) { (sender as TextBox).SelectAll(); } – Rodrigo Caballero Mar 18 '14 at 19:58
1
#region TextBoxIDCard selection
private bool textBoxIDCardGotFocus = false;
private void TextBoxIDCard_GotFocus(object sender, RoutedEventArgs e)
{
    this.TextBoxIDCard.SelectAll();
}

private void TextBoxIDCard_LostFocus(object sender, RoutedEventArgs e)
{
    textBoxIDCardGotFocus = false;
}

private void TextBoxIDCard_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    if (textBoxIDCardGotFocus == false)
    {
        e.Handled = true;
        this.TextBoxIDCard.Focus();
        textBoxIDCardGotFocus = true;
    }
} 
#endregion
Brian
  • 11
  • 1
  • If you have 20 textboxes on a window, will you create 3 methods for every textbox ? This approach is not good. Take a look here: http://rachel53461.wordpress.com/2011/11/05/automatically-selecting-textbox-text-when-focused/ – Alexandru Dicu Feb 05 '13 at 05:47
1

Try this extension method to add the desired behaviour to any TextBox control. I havn't tested it extensively yet, but it seems to fulfil my needs.

public static class TextBoxExtensions
{
    public static void SetupSelectAllOnGotFocus(this TextBox source)
    {
        source.GotFocus += SelectAll;
        source.PreviewMouseLeftButtonDown += SelectivelyIgnoreMouseButton;
    }

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

    private static void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
    {
        var textBox = (sender as TextBox);
        if (textBox != null)
        {
            if (!textBox.IsKeyboardFocusWithin)
            {
                e.Handled = true;
                textBox.Focus();
            }
        }
    }
}
David Kirkland
  • 2,431
  • 28
  • 28
0

An easy way to override the mouseDown and select all after doubleclick is:

public class DoubleClickTextBox: TextBox
{

    public override void EndInit()
    {
        base.EndInit();            
    }

    protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
    {
        base.OnMouseEnter(e);
        this.Cursor = Cursors.Arrow;
    }
    protected override void OnMouseDown(System.Windows.Input.MouseButtonEventArgs e)
    {

    }

    protected override void OnMouseDoubleClick(System.Windows.Input.MouseButtonEventArgs e)
    {
        base.OnMouseDown(e);
        this.SelectAll();
    }
}
Adi Lester
  • 24,731
  • 12
  • 95
  • 110
Hesse
  • 9
0

Try putting this in the constructor of whatever control is housing your textbox:

Loaded += (sender, e) =>
{
    MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    myTextBox.SelectAll();
}
CodeOtaku
  • 131
  • 6
0

I have tested all of them but only the following worked out:

protected override void OnStartup(StartupEventArgs e) 
{
    EventManager.RegisterClassHandler(typeof(TextBox), UIElement.PreviewMouseLeftButtonDownEvent,
   new MouseButtonEventHandler(SelectivelyHandleMouseButton), true);
    EventManager.RegisterClassHandler(typeof(TextBox), UIElement.GotKeyboardFocusEvent,
      new RoutedEventHandler(SelectAllText), true);
    EventManager.RegisterClassHandler(typeof(TextBox), UIElement.GotFocusEvent,
      new RoutedEventHandler(GotFocus), true);          
}

private static void SelectivelyHandleMouseButton(object sender, MouseButtonEventArgs e)
{
    var textbox = (sender as TextBox);
    if (textbox != null)
    {
        int hc = textbox.GetHashCode();
        if (hc == LastHashCode)
        {
            if (e.OriginalSource.GetType().Name == "TextBoxView")
            {
                e.Handled = true;
                textbox.Focus();
                LastHashCode = -1;
            }
        }
    }
    if (textbox != null) textbox.Focus();
}

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

private static int LastHashCode;
private static void GotFocus(object sender, RoutedEventArgs e)
{
    var textBox = e.OriginalSource as TextBox;
    if (textBox != null)
        LastHashCode = textBox.GetHashCode();
}
Ehsan Zargar Ershadi
  • 24,115
  • 17
  • 65
  • 95
  • 4
    That's also an obscene misuse of hash codes. I'd read this, [link](http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx) – RichK Sep 13 '11 at 08:52
  • 3
    And using `GetType().Name` instead of `is` or `as` is pretty hacky – RichK Sep 13 '11 at 08:52
0

This seems to work well for me. It's basically a recap of some earlier posts. I just put this into my MainWindow.xaml.cs file in the constructor. I create two handlers, one for keyboard, and one for the mouse, and funnel both events into the same function, HandleGotFocusEvent, which is defined right after the constructor in the same file.

public MainWindow()
{
   InitializeComponent();

   EventManager.RegisterClassHandler(typeof(TextBox), 
      UIElement.GotKeyboardFocusEvent,
      new RoutedEventHandler(HandleGotFocusEvent), true);
   EventManager.RegisterClassHandler(typeof(TextBox),
      UIElement.GotMouseCaptureEvent,
      new RoutedEventHandler(HandleGotFocusEvent), true);   
}
private void HandleGotFocusEvent(object sender, RoutedEventArgs e)
{
   if (sender is TextBox)
      (sender as TextBox).SelectAll();
}
bluish
  • 26,356
  • 27
  • 122
  • 180
Ted
  • 1
  • Nice and easy, but seems to have a timing problem - every other try (mouse click), it de-selects again immediately...? – T4NK3R Sep 18 '16 at 07:38
0

If there's an event that deselects text during the OnFocus mouse up, I usually just delay the select all.

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    if (TextBox.Text != null)
    {
        _ = Task.Run(() =>
        {
            Dispatcher.Invoke(
                async () => {
                    await Task.Delay(100);
                    TextBox.SelectAll();
                }
            );
        });
    }
}
milope
  • 346
  • 1
  • 6
0

The simplist and perfect solution, is to use a timer to select all text 20ms after textbox got focus:

Dim WithEvents Timer As New DispatcherTimer()

Set the interval: Timer.Interval = TimeSpan.FromMilliseconds(20)

respond to events (I am inheriting the TextBox control here, so I am overriding its events:

Protected Overrides Sub OnGotFocus(e As RoutedEventArgs)
        Timer.Start()
        MyBase.OnGotFocus(e)
    End Sub


    Private Sub Timer_Tick(sender As Object, e As EventArgs) Handles Timer.Tick
        Timer.Stop()
        Me.SelectAll()
    End Sub

And that is all!

Eng. M.Hamdy
  • 306
  • 1
  • 3
  • 12
0

i use this code

  private void txtNav_GotFocus(object sender, RoutedEventArgs e)
            {
                e.Handled = true;
                var c = new DispatcherTimer();
                c.Interval = TimeSpan.FromMilliseconds(100);
                c.Tick += (a1, a2) =>
                {
                    c.IsEnabled = false;
                    txtNav.SelectAll();
                };
                c.IsEnabled = true;
    
            }
hossein sedighian
  • 1,711
  • 1
  • 13
  • 16
0

This seemed to work for me...

private bool TextBoxFocusBool;

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    TextBoxFocusBool = true;
}

private void TextBox_LostMouseCapture(object sender, MouseEventArgs e)
{
    if (TextBox.SelectionLength == 0 & TextBoxFocusBool == true)
    {
        TextBox.SelectAll();
        TextBoxFocusBool = false;
    }
}

private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
    TextBoxFocusBool = true;
}
Shayne
  • 1
0

I thought this was a lot easier.

nameOfTextbox.Focus();
nameOfTextbox.Select(0, nameOfTextbox.Text.Length);

Also if someone else had the problem of your cursor not focusing on the textbox you can use this in place of nameOfTextbox.Focus(); above.

Dispatcher.BeginInvoke(DispatcherPriority.Input,
new Action(delegate () {
    nameOfTextbox.Focus();         // Set Logical Focus
    Keyboard.Focus(nameOfTextbox); // Set Keyboard Focus
}));
-1

WOW! After reading all the above I find myself overwhelmed and confused. I took what I thought I learned in this post and tried something completely different. To select the text in a TexTbox when it gets focus I use this:

private void TextField_GotFocus(object sender, RoutedEventArgs e)
{
    TextBox tb = (sender as Textbox);
    if(tb != null)
    {
        e.Handled = true;
        tb.Focus();
        tb.SelectAll();
    }
}

Set the GotFocus property of the TexTbox to this method.

Running the application and clicking once in the TexTbox highlights everything already in the TexTbox.

If indeed, the objective is to select the text when the user clicks in the TexTbox, this seems simple and involves a whole lot less code. Just saying...

GAMinTN
  • 9
  • 2
  • 2
    But when you let go of the mouse it unselects the text. So this doesn't solve the problem. – Ebsan Feb 13 '15 at 03:49
-1

For me this is working excellent after a click with the mouse on the TextBox:

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    Dispatcher.BeginInvoke(() => ((TextBox)sender).SelectAll());
    e.Handled = true;
}
root666
  • 1
  • 1