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.9k stars 2.24k forks source link

IsPointerOver does not Work with OnPointerReleased #15293

Open Elbon-Eastmage opened 7 months ago

Elbon-Eastmage commented 7 months ago

Describe the bug

When IsPointerOver is placed inside an OnPointerReleased event handler, it always returns true, even if the pointer isn't actually over the associated control.

To Reproduce

  1. Add the following XAML text to a window.
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
    <Border Name="section" PointerReleased="OnPointerReleased">
        <StackPanel>
            <TextBlock
                Text="Clickable"
                Background="LightGoldenrodYellow"
                FontSize="21"
                HorizontalAlignment="Center" />
            <TextBlock
                Name="treasure"
                Text="Hello World!"
                FontSize="21"
                Background="Gold"
                HorizontalAlignment="Center"
                IsVisible="False" />
        </StackPanel>
    </Border>
    </StackPanel>
  2. Add the following code to the window's code behind file.
    void OnPointerReleased(object sender, PointerReleasedEventArgs e)
    {
    if (section.IsPointerOver)
        treasure.IsVisible = !treasure.IsVisible;
    }
  3. Run the program.
  4. Click on the visible box, but drag the mouse away before releasing it.

Expected behavior

Since the pointer wasn't over the visible box when the mouse button was released, the hidden text shouldn't have been shown.

Avalonia version

11.0.10

OS

Windows

Additional context

No response

stevemonaco commented 7 months ago

Check the Button source for how it handles this.

In code-behind, it can be a bit simpler:

void OnPointerReleased(object sender, PointerReleasedEventArgs e)
{
    var point = e.GetCurrentPoint(section).Position;

    if (section.Bounds.Contains(point))
        treasure.IsVisible = !treasure.IsVisible;
}

This may be by-design because there are scenarios where you want IsPointerOver to be true across the entire interaction and it's easy enough to opt-out of with a small amount of code.

timunie commented 7 months ago

@Elbon-Eastmage are you happy with the provided proposal? If so, we can make this a Q&A rather than a bug report.

Elbon-Eastmage commented 7 months ago

That pull request looks perfect! Thank you!