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?


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 (eg ((TextBox)sender).Select(0, 0) ).


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 HB 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();
}

You could capture the last key pressed and compare against it in your event

private Key lastKey;
protected override void OnKeyDown(KeyEventArgs e)
{
     lastKey = e.Key;
     base.OnKeyDown(e);
}

and in your event:

private void EventSetter_OnHandler(object sender, RoutedEventArgs e)
{
    if(lastKey != Key.Tab)
        return;

    TextBox txt = sender as TextBox;
    if (txt != null) txt.SelectAll();
}

It's not perfect because they could have hit tab (not tabbing into your control) and than click into it your control. But it will work most of the time.

链接地址: http://www.djcxy.com/p/44932.html

上一篇: 文本框离开事件禁止按钮单击

下一篇: 文本框SelectAll选项卡上,而不是鼠标单击