When a C# WinForms textbox receives focus, I want it to behave like your browser's address bar.
To see what I mean, click in your web browser's address bar. You'll notice the following behavior:
I want to do exactly this in WinForms.
FASTEST GUN ALERT: please read the following before answering! Thanks guys. :-)
Calling .SelectAll() during the .Enter or .GotFocus events won't work because if the user clicked the textbox, the caret will be placed where he clicked, thus deselecting all text.
Calling .SelectAll() during the .Click event won't work because the user won't be able to select any text with the mouse; the .SelectAll() call will keep overwriting the user's text selection.
Calling BeginInvoke((Action)textbox.SelectAll) on focus/enter event enter doesn't work because it breaks rule #2 above, it will keep overriding the user's selection on focus.
This question is related to
.net
winforms
user-interface
textbox
I found a simpler solution to this. It involves kicking off the SelectAll asynchronously using Control.BeginInvoke
so that it occurs after the Enter and Click events have occurred:
In C#:
private void MyTextBox_Enter(object sender, EventArgs e)
{
// Kick off SelectAll asyncronously so that it occurs after Click
BeginInvoke((Action)delegate
{
MyTextBox.SelectAll();
});
}
In VB.NET (thanks to Krishanu Dey)
Private Sub MyTextBox_Enter(sender As Object, e As EventArgs) Handles MyTextBox.Enter
BeginInvoke(DirectCast(Sub() MyTextBox.SelectAll(), Action))
End Sub
'Inside the Enter event
TextBox1.SelectAll();
Ok, after trying it here is what you want:
This selected all the text on entry, but allowed me to highlight part of the text afterwards, or allow you to highlight on the first click.
By request:
bool entered = false;
private void textBox1_Enter(object sender, EventArgs e)
{
entered = true;
textBox1.SelectAll(); //From Jakub's answer.
}
private void textBox1_Click(object sender, EventArgs e)
{
if (entered) textBox1.SelectAll();
entered = false;
}
private void textBox1_MouseMove(object sender, MouseEventArgs e)
{
if (entered) entered = false;
}
For me, the tabbing into the control selects all the text.
This is similar to nzhenry's popular answer, but I find it easier to not have to subclass:
Private LastFocused As Control = Nothing
Private Sub TextBox1_Enter(sender As Object, e As System.EventArgs) Handles TextBox1.Enter, TextBox2.Enter, TextBox3.Enter
If MouseButtons = Windows.Forms.MouseButtons.None Then LastFocused = sender
End Sub
Private Sub TextBox1_Leave(sender As Object, e As System.EventArgs) Handles TextBox1.Leave, TextBox2.Leave, TextBox3.Leave
LastFocused = Nothing
End Sub
Private Sub TextBox1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseUp, TextBox2.MouseUp, TextBox3.MouseUp
With CType(sender, TextBox)
If LastFocused IsNot sender AndAlso .SelectionLength = 0 Then .SelectAll()
End With
LastFocused = sender
End Sub
I've found an even simpler solution:
To make sure all text is selected when clicking on a textBox, make sure that the Click handler calls the Enter handler. No need for extra variables!
Example:
private void textBox1_Click(object sender, EventArgs e){
textBox1_Enter(sender, e);
}
private void textBox1_Enter(object sender, EventArgs e){
TextBox tb = ((TextBox)sender);
tb.SelectAll();
}
The following solution works for me. I added OnKeyDown
and OnKeyUp
event override to keep the TextBox text always selected.
public class NumericTextBox : TextBox
{
private bool _focused;
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
if (MouseButtons == MouseButtons.None)
{
this.SelectAll();
_focused = true;
}
}
protected override void OnEnter(EventArgs e)
{
base.OnEnter(e);
if (MouseButtons == MouseButtons.None)
{
SelectAll();
_focused = true;
}
}
protected override void OnLeave(EventArgs e)
{
base.OnLeave(e);
_focused = false;
}
protected override void OnMouseUp(MouseEventArgs mevent)
{
base.OnMouseUp(mevent);
if (!_focused)
{
if (SelectionLength == 0)
SelectAll();
_focused = true;
}
}
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
if (SelectionLength == 0)
SelectAll();
_focused = true;
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (SelectionLength == 0)
SelectAll();
_focused = true;
}
}
'Inside the Enter event
TextBox1.SelectAll();
Ok, after trying it here is what you want:
This selected all the text on entry, but allowed me to highlight part of the text afterwards, or allow you to highlight on the first click.
By request:
bool entered = false;
private void textBox1_Enter(object sender, EventArgs e)
{
entered = true;
textBox1.SelectAll(); //From Jakub's answer.
}
private void textBox1_Click(object sender, EventArgs e)
{
if (entered) textBox1.SelectAll();
entered = false;
}
private void textBox1_MouseMove(object sender, MouseEventArgs e)
{
if (entered) entered = false;
}
For me, the tabbing into the control selects all the text.
The below seems to work. The enter event handles the tabbing to the control and the MouseDown works when the control is clicked.
private ########### void textBox1_Enter(object sender, EventArgs e)
{
textBox1.SelectAll();
}
private void textBox1_MouseDown(object sender, MouseEventArgs e)
{
if (textBox1.Focused)
textBox1.SelectAll();
}
This is similar to nzhenry's popular answer, but I find it easier to not have to subclass:
Private LastFocused As Control = Nothing
Private Sub TextBox1_Enter(sender As Object, e As System.EventArgs) Handles TextBox1.Enter, TextBox2.Enter, TextBox3.Enter
If MouseButtons = Windows.Forms.MouseButtons.None Then LastFocused = sender
End Sub
Private Sub TextBox1_Leave(sender As Object, e As System.EventArgs) Handles TextBox1.Leave, TextBox2.Leave, TextBox3.Leave
LastFocused = Nothing
End Sub
Private Sub TextBox1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseUp, TextBox2.MouseUp, TextBox3.MouseUp
With CType(sender, TextBox)
If LastFocused IsNot sender AndAlso .SelectionLength = 0 Then .SelectAll()
End With
LastFocused = sender
End Sub
I created a new VB.Net Wpf project. I created one TextBox and used the following for the codebehind:
Class MainWindow
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
AddHandler PreviewMouseLeftButtonDown, New MouseButtonEventHandler(AddressOf SelectivelyIgnoreMouseButton)
AddHandler GotKeyboardFocus, New KeyboardFocusChangedEventHandler(AddressOf SelectAllText)
AddHandler MouseDoubleClick, New MouseButtonEventHandler(AddressOf SelectAllText)
End Sub
Private Shared Sub SelectivelyIgnoreMouseButton(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
' Find the TextBox
Dim parent As DependencyObject = TryCast(e.OriginalSource, UIElement)
While parent IsNot Nothing AndAlso Not (TypeOf parent Is TextBox)
parent = VisualTreeHelper.GetParent(parent)
End While
If parent IsNot Nothing Then
Dim textBox As Object = DirectCast(parent, TextBox)
If Not textBox.IsKeyboardFocusWithin Then
' 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
End If
End If
End Sub
Private Shared Sub SelectAllText(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim textBox As Object = TryCast(e.OriginalSource, TextBox)
If textBox IsNot Nothing Then
textBox.SelectAll()
End If
End Sub
End Class
Your solution is good, but fails in one specific case. If you give the TextBox focus by selecting a range of text instead of just clicking, the alreadyFocussed flag doesn't get set to true, so when you click in the TextBox a second time, all the text gets selected.
Here is my version of the solution. I've also put the code into a class which inherits TextBox, so the logic is nicely hidden away.
public class MyTextBox : System.Windows.Forms.TextBox
{
private bool _focused;
protected override void OnEnter(EventArgs e)
{
base.OnEnter(e);
if (MouseButtons == MouseButtons.None)
{
SelectAll();
_focused = true;
}
}
protected override void OnLeave(EventArgs e)
{
base.OnLeave(e);
_focused = false;
}
protected override void OnMouseUp(MouseEventArgs mevent)
{
base.OnMouseUp(mevent);
if (!_focused)
{
if (SelectionLength == 0)
SelectAll();
_focused = true;
}
}
}
This is working for me in .NET 2005 -
' * if the mouse button is down, do not run the select all.
If MouseButtons = Windows.Forms.MouseButtons.Left Then
Exit Sub
End If
' * OTHERWISE INVOKE THE SELECT ALL AS DISCUSSED.
The below seems to work. The enter event handles the tabbing to the control and the MouseDown works when the control is clicked.
private ########### void textBox1_Enter(object sender, EventArgs e)
{
textBox1.SelectAll();
}
private void textBox1_MouseDown(object sender, MouseEventArgs e)
{
if (textBox1.Focused)
textBox1.SelectAll();
}
Your solution is good, but fails in one specific case. If you give the TextBox focus by selecting a range of text instead of just clicking, the alreadyFocussed flag doesn't get set to true, so when you click in the TextBox a second time, all the text gets selected.
Here is my version of the solution. I've also put the code into a class which inherits TextBox, so the logic is nicely hidden away.
public class MyTextBox : System.Windows.Forms.TextBox
{
private bool _focused;
protected override void OnEnter(EventArgs e)
{
base.OnEnter(e);
if (MouseButtons == MouseButtons.None)
{
SelectAll();
_focused = true;
}
}
protected override void OnLeave(EventArgs e)
{
base.OnLeave(e);
_focused = false;
}
protected override void OnMouseUp(MouseEventArgs mevent)
{
base.OnMouseUp(mevent);
if (!_focused)
{
if (SelectionLength == 0)
SelectAll();
_focused = true;
}
}
}
Here's a helper function taking the solution to the next level - reuse without inheritance.
public static void WireSelectAllOnFocus( TextBox aTextBox )
{
bool lActive = false;
aTextBox.GotFocus += new EventHandler( ( sender, e ) =>
{
if ( System.Windows.Forms.Control.MouseButtons == MouseButtons.None )
{
aTextBox.SelectAll();
lActive = true;
}
} );
aTextBox.Leave += new EventHandler( (sender, e ) => {
lActive = false;
} );
aTextBox.MouseUp += new MouseEventHandler( (sender, e ) => {
if ( !lActive )
{
lActive = true;
if ( aTextBox.SelectionLength == 0 ) aTextBox.SelectAll();
}
});
}
To use this simply call the function passing a TextBox and it takes care of all the messy bits for you. I suggest wiring up all your text boxes in the Form_Load event. You can place this function in your form, or if your like me, somewhere in a utility class for even more reuse.
I called SelectAll inside MouseUp event and it worked fine for me.
private bool _tailTextBoxFirstClick = false;
private void textBox1_MouseUp(object sender, MouseEventArgs e)
{
if(_textBoxFirstClick)
textBox1.SelectAll();
_textBoxFirstClick = false;
}
private void textBox1_Leave(object sender, EventArgs e)
{
_textBoxFirstClick = true;
textBox1.Select(0, 0);
}
It's a bit kludgey, but in your click event, use SendKeys.Send( "{HOME}+{END}" );
.
Very simple solution:
private bool _focusing = false;
protected override void OnEnter( EventArgs e )
{
_focusing = true;
base.OnEnter( e );
}
protected override void OnMouseUp( MouseEventArgs mevent )
{
base.OnMouseUp( mevent );
if( _focusing )
{
this.SelectAll();
_focusing = false;
}
}
EDIT: Original OP was in particular concerned about the mouse-down / text-selection / mouse-up sequence, in which case the above simple solution would end up with text being partially selected.
This should solve* the problem (in practice I intercept WM_SETCURSOR):
protected override void WndProc( ref Message m )
{
if( m.Msg == 32 ) //WM_SETCURSOR=0x20
{
this.SelectAll(); // or your custom logic here
}
base.WndProc( ref m );
}
*Actually the following sequence ends up with partial text selection but then if you move the mouse over the textbox all text will be selected again:
mouse-down / text-selection / mouse-move-out-textbox / mouse-up
Have you tried the solution suggested on the MSDN Forum "Windows Forms General" which simply subclasses TextBox?
I find this work best, when mouse click and not release immediately:
private bool SearchBoxInFocusAlready = false;
private void SearchBox_LostFocus(object sender, RoutedEventArgs e)
{
SearchBoxInFocusAlready = false;
}
private void SearchBox_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ButtonState == MouseButtonState.Released && e.ChangedButton == MouseButton.Left &&
SearchBox.SelectionLength == 0 && SearchBoxInFocusAlready == false)
{
SearchBox.SelectAll();
}
SearchBoxInFocusAlready = true;
}
Why don't you simply use the MouseDown-Event of the text box? It works fine for me and doesn't need an additional boolean. Very clean and simple, eg.:
private void textbox_MouseDown(object sender, MouseEventArgs e) {
if (textbox != null && !string.IsNullOrEmpty(textbox.Text))
{
textbox.SelectAll();
} }
The below seems to work. The enter event handles the tabbing to the control and the MouseDown works when the control is clicked.
private ########### void textBox1_Enter(object sender, EventArgs e)
{
textBox1.SelectAll();
}
private void textBox1_MouseDown(object sender, MouseEventArgs e)
{
if (textBox1.Focused)
textBox1.SelectAll();
}
just use selectall() on enter and click events
private void textBox1_Enter(object sender, EventArgs e)
{
textBox1.SelectAll();
}
private void textBox1_Click(object sender, EventArgs e)
{
textBox1.SelectAll();
}
This worked for a WPF/XAML TextBox.
private bool initialEntry = true;
private void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
{
if (initialEntry)
{
e.Handled = true;
initialEntry = false;
TextBox.SelectAll();
}
}
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox.SelectAll();
initialEntry = true;
}
A one line answer that I use...you might be kicking yourself...
In the Enter Event:
txtFilter.BeginInvoke(new MethodInvoker( txtFilter.SelectAll));
Have you tried the solution suggested on the MSDN Forum "Windows Forms General" which simply subclasses TextBox?
'Inside the Enter event
TextBox1.SelectAll();
Ok, after trying it here is what you want:
This selected all the text on entry, but allowed me to highlight part of the text afterwards, or allow you to highlight on the first click.
By request:
bool entered = false;
private void textBox1_Enter(object sender, EventArgs e)
{
entered = true;
textBox1.SelectAll(); //From Jakub's answer.
}
private void textBox1_Click(object sender, EventArgs e)
{
if (entered) textBox1.SelectAll();
entered = false;
}
private void textBox1_MouseMove(object sender, MouseEventArgs e)
{
if (entered) entered = false;
}
For me, the tabbing into the control selects all the text.
private bool _isSelected = false;
private void textBox_Validated(object sender, EventArgs e)
{
_isSelected = false;
}
private void textBox_MouseClick(object sender, MouseEventArgs e)
{
SelectAllText(textBox);
}
private void textBox_Enter(object sender, EventArgs e)
{
SelectAllText(textBox);
}
private void SelectAllText(TextBox text)
{
if (!_isSelected)
{
_isSelected = true;
textBox.SelectAll();
}
}
Why don't you simply use the MouseDown-Event of the text box? It works fine for me and doesn't need an additional boolean. Very clean and simple, eg.:
private void textbox_MouseDown(object sender, MouseEventArgs e) {
if (textbox != null && !string.IsNullOrEmpty(textbox.Text))
{
textbox.SelectAll();
} }
private bool _isSelected = false;
private void textBox_Validated(object sender, EventArgs e)
{
_isSelected = false;
}
private void textBox_MouseClick(object sender, MouseEventArgs e)
{
SelectAllText(textBox);
}
private void textBox_Enter(object sender, EventArgs e)
{
SelectAllText(textBox);
}
private void SelectAllText(TextBox text)
{
if (!_isSelected)
{
_isSelected = true;
textBox.SelectAll();
}
}
It's a bit kludgey, but in your click event, use SendKeys.Send( "{HOME}+{END}" );
.
Just derive a class from TextBox or MaskedTextBox:
public class SMaskedTextBox : MaskedTextBox
{
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
this.SelectAll();
}
}
And use it on your forms.
It's a bit kludgey, but in your click event, use SendKeys.Send( "{HOME}+{END}" );
.
Have you tried the solution suggested on the MSDN Forum "Windows Forms General" which simply subclasses TextBox?
SelectAll never worked for me.
This works.
ActiveControl = textBox1;
textBox1->SelectionStart = 0;
textBox1->SelectionLength = textBox1->Text->Length;
Actually GotFocus is the right event (message really) that you are interested in, since no matter how you get to the control you’ll get this even eventually. The question is when do you call SelectAll().
Try this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.textBox1.GotFocus += new EventHandler(textBox1_GotFocus);
}
private delegate void SelectAllDelegate();
private IAsyncResult _selectAllar = null; //So we can clean up afterwards.
//Catch the input focus event
void textBox1_GotFocus(object sender, EventArgs e)
{
//We could have gotten here many ways (including mouse click)
//so there could be other messages queued up already that might change the selection.
//Don't call SelectAll here, since it might get undone by things such as positioning the cursor.
//Instead use BeginInvoke on the form to queue up a message
//to select all the text after everything caused by the current event is processed.
this._selectAllar = this.BeginInvoke(new SelectAllDelegate(this._SelectAll));
}
private void _SelectAll()
{
//Clean-up the BeginInvoke
if (this._selectAllar != null)
{
this.EndInvoke(this._selectAllar);
}
//Now select everything.
this.textBox1.SelectAll();
}
}
'Inside the Enter event
TextBox1.SelectAll();
Ok, after trying it here is what you want:
This selected all the text on entry, but allowed me to highlight part of the text afterwards, or allow you to highlight on the first click.
By request:
bool entered = false;
private void textBox1_Enter(object sender, EventArgs e)
{
entered = true;
textBox1.SelectAll(); //From Jakub's answer.
}
private void textBox1_Click(object sender, EventArgs e)
{
if (entered) textBox1.SelectAll();
entered = false;
}
private void textBox1_MouseMove(object sender, MouseEventArgs e)
{
if (entered) entered = false;
}
For me, the tabbing into the control selects all the text.
Set the selction when you leave the control. It will be there when you get back. Tab around the form and when you return to the control, all the text will be selected.
If you go in by mouse, then the caret will rightly be placed at the point where you clicked.
private void maskedTextBox1_Leave(object sender, CancelEventArgs e)
{
maskedTextBox1.SelectAll();
}
Here's a helper function taking the solution to the next level - reuse without inheritance.
public static void WireSelectAllOnFocus( TextBox aTextBox )
{
bool lActive = false;
aTextBox.GotFocus += new EventHandler( ( sender, e ) =>
{
if ( System.Windows.Forms.Control.MouseButtons == MouseButtons.None )
{
aTextBox.SelectAll();
lActive = true;
}
} );
aTextBox.Leave += new EventHandler( (sender, e ) => {
lActive = false;
} );
aTextBox.MouseUp += new MouseEventHandler( (sender, e ) => {
if ( !lActive )
{
lActive = true;
if ( aTextBox.SelectionLength == 0 ) aTextBox.SelectAll();
}
});
}
To use this simply call the function passing a TextBox and it takes care of all the messy bits for you. I suggest wiring up all your text boxes in the Form_Load event. You can place this function in your form, or if your like me, somewhere in a utility class for even more reuse.
I know this was already solved but I have a suggestion that I think is actually rather simple.
In the mouse up event all you have to do is place
if(textBox.SelectionLength = 0)
{
textBox.SelectAll();
}
It seems to work for me in VB.NET (I know this is a C# question... sadly I'm forced to use VB at my job.. and I was having this issue, which is what brought me here...)
I haven't found any problems with it yet.. except for the fact that it doesn't immediately select on click, but I was having problems with that....
I found a simpler solution to this. It involves kicking off the SelectAll asynchronously using Control.BeginInvoke
so that it occurs after the Enter and Click events have occurred:
In C#:
private void MyTextBox_Enter(object sender, EventArgs e)
{
// Kick off SelectAll asyncronously so that it occurs after Click
BeginInvoke((Action)delegate
{
MyTextBox.SelectAll();
});
}
In VB.NET (thanks to Krishanu Dey)
Private Sub MyTextBox_Enter(sender As Object, e As EventArgs) Handles MyTextBox.Enter
BeginInvoke(DirectCast(Sub() MyTextBox.SelectAll(), Action))
End Sub
For a group of textboxes in a form:
private System.Windows.Forms.TextBox lastFocus;
private void textBox_GotFocus(object sender, System.Windows.Forms.MouseEventArgs e)
{
TextBox senderTextBox = sender as TextBox;
if (lastFocus!=senderTextBox){
senderTextBox.SelectAll();
}
lastFocus = senderTextBox;
}
This is working for me in .NET 2005 -
' * if the mouse button is down, do not run the select all.
If MouseButtons = Windows.Forms.MouseButtons.Left Then
Exit Sub
End If
' * OTHERWISE INVOKE THE SELECT ALL AS DISCUSSED.
just use selectall() on enter and click events
private void textBox1_Enter(object sender, EventArgs e)
{
textBox1.SelectAll();
}
private void textBox1_Click(object sender, EventArgs e)
{
textBox1.SelectAll();
}
I know this was already solved but I have a suggestion that I think is actually rather simple.
In the mouse up event all you have to do is place
if(textBox.SelectionLength = 0)
{
textBox.SelectAll();
}
It seems to work for me in VB.NET (I know this is a C# question... sadly I'm forced to use VB at my job.. and I was having this issue, which is what brought me here...)
I haven't found any problems with it yet.. except for the fact that it doesn't immediately select on click, but I was having problems with that....
Interestingly, a ComboBox with DropDownStyle=Simple has pretty much exactly the behaviour you are looking for, I think.
(If you reduce the height of the control to not show the list - and then by a couple of pixels more - there's no effective difference between the ComboBox and the TextBox.)
Actually GotFocus is the right event (message really) that you are interested in, since no matter how you get to the control you’ll get this even eventually. The question is when do you call SelectAll().
Try this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.textBox1.GotFocus += new EventHandler(textBox1_GotFocus);
}
private delegate void SelectAllDelegate();
private IAsyncResult _selectAllar = null; //So we can clean up afterwards.
//Catch the input focus event
void textBox1_GotFocus(object sender, EventArgs e)
{
//We could have gotten here many ways (including mouse click)
//so there could be other messages queued up already that might change the selection.
//Don't call SelectAll here, since it might get undone by things such as positioning the cursor.
//Instead use BeginInvoke on the form to queue up a message
//to select all the text after everything caused by the current event is processed.
this._selectAllar = this.BeginInvoke(new SelectAllDelegate(this._SelectAll));
}
private void _SelectAll()
{
//Clean-up the BeginInvoke
if (this._selectAllar != null)
{
this.EndInvoke(this._selectAllar);
}
//Now select everything.
this.textBox1.SelectAll();
}
}
I've found an even simpler solution:
To make sure all text is selected when clicking on a textBox, make sure that the Click handler calls the Enter handler. No need for extra variables!
Example:
private void textBox1_Click(object sender, EventArgs e){
textBox1_Enter(sender, e);
}
private void textBox1_Enter(object sender, EventArgs e){
TextBox tb = ((TextBox)sender);
tb.SelectAll();
}
Why don't you simply use the MouseDown-Event of the text box? It works fine for me and doesn't need an additional boolean. Very clean and simple, eg.:
private void textbox_MouseDown(object sender, MouseEventArgs e) {
if (textbox != null && !string.IsNullOrEmpty(textbox.Text))
{
textbox.SelectAll();
} }
Very simple solution:
private bool _focusing = false;
protected override void OnEnter( EventArgs e )
{
_focusing = true;
base.OnEnter( e );
}
protected override void OnMouseUp( MouseEventArgs mevent )
{
base.OnMouseUp( mevent );
if( _focusing )
{
this.SelectAll();
_focusing = false;
}
}
EDIT: Original OP was in particular concerned about the mouse-down / text-selection / mouse-up sequence, in which case the above simple solution would end up with text being partially selected.
This should solve* the problem (in practice I intercept WM_SETCURSOR):
protected override void WndProc( ref Message m )
{
if( m.Msg == 32 ) //WM_SETCURSOR=0x20
{
this.SelectAll(); // or your custom logic here
}
base.WndProc( ref m );
}
*Actually the following sequence ends up with partial text selection but then if you move the mouse over the textbox all text will be selected again:
mouse-down / text-selection / mouse-move-out-textbox / mouse-up
The answer can be actually quite more simple than ALL of the above, for example (in WPF):
public void YourTextBox_MouseEnter(object sender, MouseEventArgs e)
{
YourTextBox.Focus();
YourTextBox.SelectAll();
}
of course I can't know how you want to use this code, but the main part to look at here is: First call .Focus() and then call .SelectAll();
Why don't you simply use the MouseDown-Event of the text box? It works fine for me and doesn't need an additional boolean. Very clean and simple, eg.:
private void textbox_MouseDown(object sender, MouseEventArgs e) {
if (textbox != null && !string.IsNullOrEmpty(textbox.Text))
{
textbox.SelectAll();
} }
Click event of textbox? Or even MouseCaptureChanged event works for me. - OK. doesn't work.
So you have to do 2 things:
private bool f = false;
private void textBox_MouseClick(object sender, MouseEventArgs e)
{
if (this.f) { this.textBox.SelectAll(); }
this.f = false;
}
private void textBox_Enter(object sender, EventArgs e)
{
this.f = true;
this.textBox.SelectAll();
}
private void textBox_MouseMove(object sender, MouseEventArgs e) // idea from the other answer
{
this.f = false;
}
Works for tabbing (through textBoxes to the one) as well - call SelectAll() in Enter just in case...
It's a bit kludgey, but in your click event, use SendKeys.Send( "{HOME}+{END}" );
.
This worked for a WPF/XAML TextBox.
private bool initialEntry = true;
private void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
{
if (initialEntry)
{
e.Handled = true;
initialEntry = false;
TextBox.SelectAll();
}
}
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox.SelectAll();
initialEntry = true;
}
Click event of textbox? Or even MouseCaptureChanged event works for me. - OK. doesn't work.
So you have to do 2 things:
private bool f = false;
private void textBox_MouseClick(object sender, MouseEventArgs e)
{
if (this.f) { this.textBox.SelectAll(); }
this.f = false;
}
private void textBox_Enter(object sender, EventArgs e)
{
this.f = true;
this.textBox.SelectAll();
}
private void textBox_MouseMove(object sender, MouseEventArgs e) // idea from the other answer
{
this.f = false;
}
Works for tabbing (through textBoxes to the one) as well - call SelectAll() in Enter just in case...
The following solution works for me. I added OnKeyDown
and OnKeyUp
event override to keep the TextBox text always selected.
public class NumericTextBox : TextBox
{
private bool _focused;
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
if (MouseButtons == MouseButtons.None)
{
this.SelectAll();
_focused = true;
}
}
protected override void OnEnter(EventArgs e)
{
base.OnEnter(e);
if (MouseButtons == MouseButtons.None)
{
SelectAll();
_focused = true;
}
}
protected override void OnLeave(EventArgs e)
{
base.OnLeave(e);
_focused = false;
}
protected override void OnMouseUp(MouseEventArgs mevent)
{
base.OnMouseUp(mevent);
if (!_focused)
{
if (SelectionLength == 0)
SelectAll();
_focused = true;
}
}
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
if (SelectionLength == 0)
SelectAll();
_focused = true;
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (SelectionLength == 0)
SelectAll();
_focused = true;
}
}
My Solution is pretty primitive but works fine for my purpose
private async void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
if (sender is TextBox)
{
await Task.Delay(100);
(sender as TextBox).SelectAll();
}
}
Set the selction when you leave the control. It will be there when you get back. Tab around the form and when you return to the control, all the text will be selected.
If you go in by mouse, then the caret will rightly be placed at the point where you clicked.
private void maskedTextBox1_Leave(object sender, CancelEventArgs e)
{
maskedTextBox1.SelectAll();
}
private bool _isSelected = false;
private void textBox_Validated(object sender, EventArgs e)
{
_isSelected = false;
}
private void textBox_MouseClick(object sender, MouseEventArgs e)
{
SelectAllText(textBox);
}
private void textBox_Enter(object sender, EventArgs e)
{
SelectAllText(textBox);
}
private void SelectAllText(TextBox text)
{
if (!_isSelected)
{
_isSelected = true;
textBox.SelectAll();
}
}
Click event of textbox? Or even MouseCaptureChanged event works for me. - OK. doesn't work.
So you have to do 2 things:
private bool f = false;
private void textBox_MouseClick(object sender, MouseEventArgs e)
{
if (this.f) { this.textBox.SelectAll(); }
this.f = false;
}
private void textBox_Enter(object sender, EventArgs e)
{
this.f = true;
this.textBox.SelectAll();
}
private void textBox_MouseMove(object sender, MouseEventArgs e) // idea from the other answer
{
this.f = false;
}
Works for tabbing (through textBoxes to the one) as well - call SelectAll() in Enter just in case...
Interestingly, a ComboBox with DropDownStyle=Simple has pretty much exactly the behaviour you are looking for, I think.
(If you reduce the height of the control to not show the list - and then by a couple of pixels more - there's no effective difference between the ComboBox and the TextBox.)
The below seems to work. The enter event handles the tabbing to the control and the MouseDown works when the control is clicked.
private ########### void textBox1_Enter(object sender, EventArgs e)
{
textBox1.SelectAll();
}
private void textBox1_MouseDown(object sender, MouseEventArgs e)
{
if (textBox1.Focused)
textBox1.SelectAll();
}
I created a new VB.Net Wpf project. I created one TextBox and used the following for the codebehind:
Class MainWindow
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
AddHandler PreviewMouseLeftButtonDown, New MouseButtonEventHandler(AddressOf SelectivelyIgnoreMouseButton)
AddHandler GotKeyboardFocus, New KeyboardFocusChangedEventHandler(AddressOf SelectAllText)
AddHandler MouseDoubleClick, New MouseButtonEventHandler(AddressOf SelectAllText)
End Sub
Private Shared Sub SelectivelyIgnoreMouseButton(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
' Find the TextBox
Dim parent As DependencyObject = TryCast(e.OriginalSource, UIElement)
While parent IsNot Nothing AndAlso Not (TypeOf parent Is TextBox)
parent = VisualTreeHelper.GetParent(parent)
End While
If parent IsNot Nothing Then
Dim textBox As Object = DirectCast(parent, TextBox)
If Not textBox.IsKeyboardFocusWithin Then
' 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
End If
End If
End Sub
Private Shared Sub SelectAllText(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim textBox As Object = TryCast(e.OriginalSource, TextBox)
If textBox IsNot Nothing Then
textBox.SelectAll()
End If
End Sub
End Class
Just derive a class from TextBox or MaskedTextBox:
public class SMaskedTextBox : MaskedTextBox
{
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
this.SelectAll();
}
}
And use it on your forms.
Interestingly, a ComboBox with DropDownStyle=Simple has pretty much exactly the behaviour you are looking for, I think.
(If you reduce the height of the control to not show the list - and then by a couple of pixels more - there's no effective difference between the ComboBox and the TextBox.)
The answer can be actually quite more simple than ALL of the above, for example (in WPF):
public void YourTextBox_MouseEnter(object sender, MouseEventArgs e)
{
YourTextBox.Focus();
YourTextBox.SelectAll();
}
of course I can't know how you want to use this code, but the main part to look at here is: First call .Focus() and then call .SelectAll();
My Solution is pretty primitive but works fine for my purpose
private async void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
if (sender is TextBox)
{
await Task.Delay(100);
(sender as TextBox).SelectAll();
}
}
I find this work best, when mouse click and not release immediately:
private bool SearchBoxInFocusAlready = false;
private void SearchBox_LostFocus(object sender, RoutedEventArgs e)
{
SearchBoxInFocusAlready = false;
}
private void SearchBox_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ButtonState == MouseButtonState.Released && e.ChangedButton == MouseButton.Left &&
SearchBox.SelectionLength == 0 && SearchBoxInFocusAlready == false)
{
SearchBox.SelectAll();
}
SearchBoxInFocusAlready = true;
}
A one line answer that I use...you might be kicking yourself...
In the Enter Event:
txtFilter.BeginInvoke(new MethodInvoker( txtFilter.SelectAll));
For a group of textboxes in a form:
private System.Windows.Forms.TextBox lastFocus;
private void textBox_GotFocus(object sender, System.Windows.Forms.MouseEventArgs e)
{
TextBox senderTextBox = sender as TextBox;
if (lastFocus!=senderTextBox){
senderTextBox.SelectAll();
}
lastFocus = senderTextBox;
}
Click event of textbox? Or even MouseCaptureChanged event works for me. - OK. doesn't work.
So you have to do 2 things:
private bool f = false;
private void textBox_MouseClick(object sender, MouseEventArgs e)
{
if (this.f) { this.textBox.SelectAll(); }
this.f = false;
}
private void textBox_Enter(object sender, EventArgs e)
{
this.f = true;
this.textBox.SelectAll();
}
private void textBox_MouseMove(object sender, MouseEventArgs e) // idea from the other answer
{
this.f = false;
}
Works for tabbing (through textBoxes to the one) as well - call SelectAll() in Enter just in case...
SelectAll never worked for me.
This works.
ActiveControl = textBox1;
textBox1->SelectionStart = 0;
textBox1->SelectionLength = textBox1->Text->Length;
Have you tried the solution suggested on the MSDN Forum "Windows Forms General" which simply subclasses TextBox?
I called SelectAll inside MouseUp event and it worked fine for me.
private bool _tailTextBoxFirstClick = false;
private void textBox1_MouseUp(object sender, MouseEventArgs e)
{
if(_textBoxFirstClick)
textBox1.SelectAll();
_textBoxFirstClick = false;
}
private void textBox1_Leave(object sender, EventArgs e)
{
_textBoxFirstClick = true;
textBox1.Select(0, 0);
}
private bool _isSelected = false;
private void textBox_Validated(object sender, EventArgs e)
{
_isSelected = false;
}
private void textBox_MouseClick(object sender, MouseEventArgs e)
{
SelectAllText(textBox);
}
private void textBox_Enter(object sender, EventArgs e)
{
SelectAllText(textBox);
}
private void SelectAllText(TextBox text)
{
if (!_isSelected)
{
_isSelected = true;
textBox.SelectAll();
}
}
Interestingly, a ComboBox with DropDownStyle=Simple has pretty much exactly the behaviour you are looking for, I think.
(If you reduce the height of the control to not show the list - and then by a couple of pixels more - there's no effective difference between the ComboBox and the TextBox.)
Source: Stackoverflow.com