9

I have a TextBox and I want all the text inside of it to be highlighted when the user clicks on it (so that they can replace it easily). I have the following event handler linked up the the TextBox:

private void TextBox_Enter(object sender, EventArgs e) {
    SelectAll();
}

When I click on the TextBox, the text is only selected for a fraction of a second (sometime it's so fast I can't see it at all) and then it goes back to being a cursor. Does anyone know how to fix this or if there are any relatively simple workarounds?

I tried the same thing with the TextBox.MouseClick event (and it highlighted the text), but because it was the MouseClick event the text was highlighted every time I clicked the TextBox (even when the TextBox already had focus).

I have also tried SelectionStart = 0; SelectionLength = Text.Length, but the same thing happens. This leads me be believe the issue has something to do with the event.

I also tried the TextBox.GotFocus event and had the exact same problem.

I am doing this in a Windows Form application.

BionicCode
  • 1
  • 4
  • 28
  • 44
Commonaught
  • 340
  • 5
  • 11

2 Answers2

22

The reason why you didn't see the text getting selected is that the TextBox is busy when one of those events occurred (e.g., caret positioning). You actually select the text, but then the internal event handlers of the TextBox execute and remove the selection e.g. by setting the caret position.

All you have to do is to wait until the internal event handlers have completed.
You do this by using the Dispatcher. When you invoke the Dispatcher asynchronously the delegate is not immediately executed but enqueued and executed once all previously enqueued actions (like the internal event handlers) are cleared from the dispatcher queue.

So going with the TextBox.GotFocus event in WPF (or the TextBox.Enter in WinForms) and the asynchronous Dispatcher will do the trick:

WPF

private async void SelectAll_OnTextBoxGotFocus(object sender, RoutedEventArgs e)
{
  await Application.Current.Dispatcher.InvokeAsync((sender as TextBox).SelectAll);
}

WinForms

private void SelectAll_OnTextBoxEnter(object sender, EventArgs e)
{
  var textBox = sender as TextBox;
  textBox.BeginInvoke(new Action(textBox.SelectAll));
}
BionicCode
  • 1
  • 4
  • 28
  • 44
  • Are you writing a WinForms application? – BionicCode Jan 02 '20 at 20:10
  • 1
    You also tagged it WPF. My current answer is targeting WPF. Let me add the corresponding WinForms solution. Hold on. – BionicCode Jan 02 '20 at 20:17
  • 2
    I've added a WinForms example. – BionicCode Jan 02 '20 at 20:22
  • Yes sorry didn't validated it. Was a copy & paste remainder from the previous WPF example. I also updated the delegate of the `textBox.BeginInvoke`. – BionicCode Jan 02 '20 at 20:31
  • Yep, came to that conclusion too. With the edit it works like a charm. – Commonaught Jan 02 '20 at 20:34
  • Last remark. As I assumed you were using WPF at first, I recommended to use the `GotFocus` event. Since you are using WinForms [Microsoft recommends](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.gotfocus?view=netframework-4.8#remarks) to use the `Enter` event instead. In WinForms the `GotFocus` will also work but should only be used when listening to a custom control. When listening to a `Form` use the `Form.Activated` event. – BionicCode Jan 02 '20 at 20:54
  • Noted. Thanks for the help. – Commonaught Jan 02 '20 at 21:07
  • Thank you for this explanation! This makes sense now... I was struggling getting my text properly focus after mouse click, you saved me. – IFrank May 06 '23 at 08:45
  • @IFrank I'm glad you found this post helpful. Good luck with your project. – BionicCode May 06 '23 at 15:45
  • 1
    Just tested. This works – Syed Irfan Ahmad Aug 11 '23 at 18:29
0

Thankfully I found a solution! It turns out that the Click event is executed before the Enter event, this allowed me to set up a JustGotFocus variable and do the following:

private void myTextBox_Click(object sender, EventArgs e) {

    this.JustGotFocus = true;

    if (JustGotFocus) {
        myTextBox.SelectAll();
    }
}

private void myTextBox_Enter(object sender, EventArgs e) {
    JustGotFocus = false;
}

If anyone else has this problem hopefully my solution is useful.

Commonaught
  • 340
  • 5
  • 11