unoplatform / uno

Open-source platform for building cross-platform native Mobile, Web, Desktop and Embedded apps quickly. Create rich, C#/XAML, single-codebase apps from any IDE. Hot Reload included! 90m+ NuGet Downloads!!
https://platform.uno
Apache License 2.0
8.93k stars 725 forks source link

` VisualTreeHelper.FindElementsInHostCoordinates()` returns different subtree values for controls on `Canvas` ( UWP vs WASM) #4073

Open ToddGlodek opened 4 years ago

ToddGlodek commented 4 years ago

I have code that calls VisualTreeHelper.FindElementsInHostCoordinates() in to return all the controls beneath pointer when OnPointerPressed() is triggered. The same code produces different results when complied as UWP vs WASM (even if you hard code the value of pagePoint to ensure that it its with a particular control).

var elementsAtPosit = VisualTreeHelper.FindElementsInHostCoordinates(pagePoint, theCanvas);

Current behavior

I have a Uno.Shared project which features a Canvas and a bunch of UserControls (Circles & Squares). I have written a work around to the UNO drag and drop limitations that I can use to reposition all the various Circles and Squares on the parent Canvas. When the code runs as UWP, it returns the desired control subtree (all the appropriate overlapping Circles and Squares plus the Canvas control). When running the WASM code, only the Canvas control is returned.

Expected behavior

The same list of controls should be returned by both UWP and WASM version of the code.

How to reproduce it (as minimally and precisely as possible)

  1. Create a project page that features a Canvas control
  2. Place some content (eg: Circles & Squares) on the Canvas
  3. Implement an event handler for OnPointerPressed(PointerRoutedEventArgs e) that captures the 'click'
  4. Within the event handler call VisualTreeHelper.FindElementsInHostCoordinates() to get controls at specified x-y coordinate
  5. Write the resulting list of controls to the log/debuger trace.
  6. Run the code on both UWP/WASM and then click on the some of the Circles & Squares
  7. Compare the logs.
  8. Observe that the list of controls is different between UWP &WASM

Workaround

  1. Because I am working with custom classes derived from UserControl I was able to do the following:
  2. I made a subclass of the view model especially for WASM that contained an ObservableCollection
  3. In myControl I added event handlers for PointerEntered() & PointerExited() that added/removed items from the collection in view model

    private IEnumerable GetUIElementsAtPointerPosition(PointerRoutedEventArgs e) { var rtnList = new List();

        Point pagePoint = GetPagePoint(e);

if ! WASM COMPILER DIRECTIVE*/

        var elementsAtPosit = VisualTreeHelper.FindElementsInHostCoordinates(pagePoint, theCanvas);

else

        var elementsAtPosit = (this.DataContext as DrawingSurfaceViewModelWASM).ControlsBeneathPointer.AsEnumerable();

endif

... }

This technique produced the desired list of controls

Environment

Nuget Package:

Nuget Package Version(s):

Affected platform(s):

IDE:

Relevant plugins:

Anything else we need to know?

ToddGlodek commented 4 years ago

I noticed that the code I wrote no longer works the way it did previously - yet VisualTreeHelper.cs does not appears to have changed since Mar 20.

Would something have changed recently beneath the covers somewhere to alter the behavior of FindElementsInHostCoordinates(). The enumeration is now empty on UWP as well.

I believe at the time I was using :

    <PackageReference Include="Uno.UI" Version="3.1.0-dev.465" />
    <PackageReference Include="Uno.UI.RemoteControl" Version="3.1.0-dev.465" Condition="'$(Configuration)'=='Debug'" />
    <PackageReference Include="Uno.UI.WebAssembly" Version="3.1.0-dev.465" />

Whereas now I am using

<PackageReference Include="Uno.UI" Version="3.1.0-dev.739" />
<PackageReference Include="Uno.UI.RemoteControl" Version="3.1.0-dev.739" Condition="'$(Configuration)'=='Debug'" />
<PackageReference Include="Uno.UI.WebAssembly" Version="3.1.0-dev.739" />
<PackageReference Include="Uno.Wasm.Bootstrap" Version="1.5.0-dev.57" />
<PackageReference Include="Uno.Wasm.Bootstrap.DevServer" Version="1.5.0-dev.57" />

Strange ??

davidjohnoliver commented 4 years ago

If the enumeration is empty on UWP, the difference is most likely in your own code - Uno is not used when running on UWP.

MartinZikmund commented 3 years ago

@ToddGlodek is this still an issue for you?

ToddGlodek commented 3 years ago

Thanks for the follow up. I haven’t looked at it in a long time …

I will go back and check it out. I’ll update all the dependencies with new versions and let you know.

Sent from Mailhttps://go.microsoft.com/fwlink/?LinkId=550986 for Windows 10

From: Martin @.> Sent: Wednesday, June 2, 2021 4:33 AM To: @.> Cc: @.>; @.> Subject: Re: [unoplatform/uno] VisualTreeHelper.FindElementsInHostCoordinates() returns different subtree values for controls on Canvas ( UWP vs WASM) (#4073)

@ToddGlodekhttps://github.com/ToddGlodek is this still an issue for you?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/unoplatform/uno/issues/4073#issuecomment-852951433, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AEWZKHI67ZLD5E3377TVO5DTQYJJJANCNFSM4RSWMCAQ.

ToddGlodek commented 2 years ago

I suspect that the underling cause for this issue will turn out to have been Loading, Loaded & Unloaded events are called too early #2895. I documented, what feels to be a very similar set of symptoms, as part of Page Loading Fails - Potentially because 2 nested XAML controls in a direct parent/child get instantiated/InitializeComponented/loaded in different order between WASM / WinUI #10276. I believe #2895 is whats causing this behavior too.