Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Textbox SelectAll on tab but not mouse click

So lets say I have a WPF form with several text boxes, if you tab to the text box and it already has something in it, I want to select all the text in that box so typing will erase that text. If you mouse click on the box, it probably means you want to change a letter somewhere, so do not highlight all in this case. Seems easy enough, but a good solution as so far eluded me. Here's what I have so far that is very close to working, but not quite perfect.

<Style x:Key="TextBoxStyle" TargetType="TextBox">
    <EventSetter Event="GotKeyboardFocus" Handler="EventSetter_OnHandler" />
</Style>

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

So when the box gets keyboard focus it selects all, so tabbing to the text box selects all the text perfectly. However if the mouse clicks this method gets called as well, which also highlights the text, but the click then puts the cursor where the mouse clicked after. So functionally it's perfect, but it still bothers me that it flickers selecting everything when the mouse clicks. Any better way to do this, or put some kind of check in my event to know that I gained keyboard focus from a mouse click and not a tab?

like image 244
Kevin DiTraglia Avatar asked Aug 02 '12 22:08

Kevin DiTraglia


2 Answers

Have not seen any clean solution so far sadly, one thing you could do is just check the mouse state:

var tb = (TextBox)sender;
if (Mouse.LeftButton != MouseButtonState.Pressed)
    tb.SelectAll();

But there actually is a better way, as the focus shifts on key down you can check the keyboard instead. I would recommend using the proper signature for the GotKeyboardFocus handler to get the appropriate event-args:

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

At this point you may still see some selection getting cleared upon click but that is just because the previous selection only gets hidden if unfocused. You can always clear the selection in LostKeyboardFocus to prevent that (e.g. ((TextBox)sender).Select(0, 0)).

like image 59
H.B. Avatar answered Sep 19 '22 15:09

H.B.


You could try checking if the Mouse is present in the TextBox when the Focus Event happens and check the Mouse ButtonButtonState. This is not perfect but should be close to what you are looking for.

private void EventSetter_OnHandler(object sender, RoutedEventArgs e)
{
    TextBox txt = sender as TextBox;
    Point position = Mouse.GetPosition(txt);
    // if Mouse position is not in the TextBox Client Rectangle
    // and Mouse Button not Pressed.
    if((!(new Rect(0,0,txt.Width,txt.Height)).Contains(position)) || ( Mouse.LeftButton != MouseButtonState.Pressed))
        if (txt != null) txt.SelectAll();
}

and as H.B. Pointed out you could try using the txt.IsMouseOver Property to determine if the Cursor is inside the TextBox's Client Rectangle. It looks a lot cleaner.

private void EventSetter_OnHandler(object sender, RoutedEventArgs e)
{
    TextBox txt = sender as TextBox;
    if( !txt.IsMouseOver || Mouse.LeftButton != MouseButtonState.Pressed)
        if (txt != null) txt.SelectAll();
}
like image 42
Mark Hall Avatar answered Sep 18 '22 15:09

Mark Hall