Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Bug in .NET 8: GetVisualTreeElements(point) is now broken and won't run at all, says "MauiContext should have been set on parent." #18070

Closed
jonmdev opened this issue Oct 17, 2023 · 3 comments

Comments

@jonmdev
Copy link

jonmdev commented Oct 17, 2023

Description

Previously, IVisualTreeElement.GetVisualTreeElements(point) from Microsoft.Maui.VisualTreeElementExtensions worked, allowing us to get a list of elements at a given point. This was fine in .NET 7.

However, I upgraded to .NET 8 to try to benefit from other bug fixes and this no longer works. Now any attempt to run it results in the error MauiContext should have been set on parent.

Is there any way this could be fixed?

Steps to Reproduce

Open the repro, play project, click anywhere on screen to run the function, get the bug error result in .NET 8 but not .NET 7.

Code replacing App.xaml.cs in default project:

using System.Diagnostics;

namespace Get_Visual_Tree_Bug {
    public partial class App : Application {
        ContentPage mainPage;
        AbsoluteLayout abs;
        public App() {
            InitializeComponent();

            mainPage = new();
            mainPage.BackgroundColor = Colors.Black;
            MainPage = mainPage;

            List<View> resizeList = new();

            abs = new();
            mainPage.Content = abs;
            resizeList.Add(abs);
            
            AbsoluteLayout abs2 = new();
            abs.Add(abs2);
            resizeList.Add(abs2);

            VerticalStackLayout vert = new();
            abs2.Add(vert);
            resizeList.Add(vert);

            Border border = new();
            border.BackgroundColor = Colors.Green;
            vert.Add(border);
            resizeList.Add(border);

            TapGestureRecognizer tap = new();
            tap.Tapped += (s, e) => {
                checkTargets((Point)e.GetPosition(border));
            };
            border.GestureRecognizers.Add(tap); 

            mainPage.SizeChanged += delegate {
                for (int i = 0; i < resizeList.Count; i++) {
                    resizeList[i].HeightRequest = mainPage.Height;
                    resizeList[i].WidthRequest = mainPage.Width;

                }
            };
        }
        public void checkTargets(Point point) {

            var elementsList = mainPage.GetVisualTreeElements(point); //broken
            //var elementsList = abs.GetVisualTreeElements(point); //broken

            for (int i = 0; i < elementsList.Count; i++) {
                if (elementsList[i] as VisualElement != null) {
                    VisualElement element = elementsList[i] as VisualElement;
                    if (element != null) {
                        Debug.WriteLine("FOUND at point " + point + ": " + element.GetType());
                    }
                }

            }
        }
    }
}

Link to public reproduction project repository

https://github.com/jonmdev/Get-Visual-Tree-Bug

Version with bug

8.0.0-rc.1.9171

Is this a regression from previous behavior?

Yes, this used to work in .NET MAUI

Last version that worked well

7.0.96

Affected platforms

iOS, Android, Windows

Affected platform versions

All .NET 8

Did you find any workaround?

Nope.

Relevant log output

No response

@jonmdev jonmdev added the t/bug Something isn't working label Oct 17, 2023
@drasticactions
Copy link
Contributor

drasticactions commented Oct 17, 2023

image

Your example works fine. But I know what it takes to get that error to happen.

Border border = new();
border.StrokeShape = new Microsoft.Maui.Controls.Shapes.RoundRectangle() { CornerRadius = 10 };
border.BackgroundColor = Colors.Green;

Add a shape, and it'll throw. Because of #16919. So I'm 99% sure in the context of your application, you probably have a shape or some element without a handler, which will cause this to throw. The API for GetVisualTreeElements hasn't changed since it was introduced, AFAIK. The reason it's throwing now is because of

#14132
#16046

These added border shapes to the logical children list (which is correct). But shapes (or potentially other objects) don't have handlers, and the underlying logic for getting the platform view assumes they do (because they should, it's listed as non-nullable) which is why it's broken now.

#16919 needs to be fixed to fix this issue.

e. Also, as a heads up, unless you're using this for debug tooling, I would not use that API in a real-world application. It's intended for Visual Diagnostics tooling and is not designed to be efficient in a real-world usecase. Depending on what you're doing, there are probably other ways to do what you need that would be better.

@jonmdev
Copy link
Author

jonmdev commented Oct 17, 2023

image

Your example works fine. But I know what it takes to get that error to happen.

Border border = new();
border.StrokeShape = new Microsoft.Maui.Controls.Shapes.RoundRectangle() { CornerRadius = 10 };
border.BackgroundColor = Colors.Green;

Add a shape, and it'll throw. Because of #16919. So I'm 99% sure in the context of your application, you probably have a shape or some element without a handler, which will cause this to throw. The API for GetVisualTreeElements hasn't changed since it was introduced, AFAIK. The reason it's throwing now is because of

#14132 #16046

These added border shapes to the logical children list (which is correct). But shapes (or potentially other objects) don't have handlers, and the underlying logic for getting the platform view assumes they do (because they should, it's listed as non-nullable) which is why it's broken now.

#16919 needs to be fixed to fix this issue.

e. Also, as a heads up, unless you're using this for debug tooling, I would not use that API in a real-world application. It's intended for Visual Diagnostics tooling and is not designed to be efficient in a real-world usecase. Depending on what you're doing, there are probably other ways to do what you need that would be better.

You are right, it is the Border that is doing it. If I comment out:

//vert.Add(border);
//resizeList.Add(border);

...the error stops showing.

I do not need to add a Stroke Shape as you suggest. I presume this means the Border already has a default Stroke Shape if that is the source of the problem. Or perhaps we are using different versions if you don't have the bug on my demo project?

For me, I can just open the project, play it in .NET 8.0.0-rc.1.9171 and click on screen and get that error with the project exactly as written in my OP. Happens in Windows and Android for sure at least every time.

As for the performance of this function, to my knowledge there is nothing that replaces it although I may have to write my own version by copying/pasting/editing the code for it eventually. I am overriding all hit detection functions with an overlay layer similar to WindowOverlay included in Maui (built it based on that) and therefore need a function that can detect all elements at a spot on screen so I can decide who gets the hit.

The only other problem with this function is it does not behave as I would like for detecting "invisible" objects. If you don't add a background color to layout elements, for example, it goes straight through them and they are not detected. I need to test this more but it is certainly a problem on Windows for me.

Any further thoughts are appreciated, but at this point just getting the Border glitch fixed is critical as now this function is completely unusable in .NET 8.0 unless there are no Borders on screen. Thanks for your feedback and work on it. I appreciate at least knowing where it's coming from.

@samhouts
Copy link
Member

Duplicate of #16919

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants