AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
25.8k stars 2.23k forks source link

TextBox text unselected when getting focus trough mouse click. #16825

Open mateli opened 2 months ago

mateli commented 2 months ago

Describe the bug

If a textbox get focus by clicking then selected text is deselected.

To Reproduce

mybox.GotFocus += (, ) => mybox.SelectAll();

Expected behavior

With the code above mybox should whenever it get focus select all text which it does. However it seems that when it get's focus from a pointer event it deselects all text and it does that after the focus event code has been run.

Avalonia version

11.1.3

OS

No response

Additional context

No response

stevemonaco commented 2 months ago

You need to handle the pointer event so that the TextBox will not, at least for this narrow scenario (and allow it to handle other scenarios). I've written an attached behavior for this which should work for either clicking or any other focus-related trigger (like tab navigation).

public class TextBoxFocusSelectionBehavior : Behavior<TextBox>
{
    /// <inheritdoc />
    protected override void OnAttachedToVisualTree()
    {
        AssociatedObject?.AddHandler(InputElement.GotFocusEvent, AssociatedObject_GotFocus, RoutingStrategies.Bubble);
        AssociatedObject?.AddHandler(InputElement.PointerPressedEvent, AssociatedObject_PreviewPointerPressed, RoutingStrategies.Tunnel);
    }

    /// <inheritdoc />
    protected override void OnDetachedFromVisualTree()
    {
        AssociatedObject?.RemoveHandler(InputElement.GotFocusEvent, AssociatedObject_GotFocus);
        AssociatedObject?.RemoveHandler(InputElement.PointerPressedEvent, AssociatedObject_PreviewPointerPressed);
    }

    private void AssociatedObject_GotFocus(object? sender, GotFocusEventArgs e)
    {
        AssociatedObject?.SelectAll();
    }

    private void AssociatedObject_PreviewPointerPressed(object? sender, PointerPressedEventArgs e)
    {
        if (AssociatedObject?.IsKeyboardFocusWithin is false)
        {
            AssociatedObject.Focus();
            e.Handled = true;
        }
    }
}

If you don't wish to use behaviors, you can follow the event implementation above. You still need to subscribe to PointerPressed with a tunneling event (not a bubbling event like you're doing).

rabbitism commented 2 months ago

related: https://github.com/AvaloniaUI/Avalonia/issues/11693