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

[BUG] Prism and MauiCompatibility are incompatibile on Windows #3173

Open
clnoel opened this issue Jun 26, 2024 · 6 comments
Open

[BUG] Prism and MauiCompatibility are incompatibile on Windows #3173

clnoel opened this issue Jun 26, 2024 · 6 comments
Labels

Comments

@clnoel
Copy link

clnoel commented Jun 26, 2024

Description

This is a revival of PrismLibrary/Prism.Maui#76 but with more info... it is a Prism bug, or at least a DryIoC one.

I've spent a huge amount of time digging through Prism and Maui code to locate this bug, but I don't know how you want to fix it on your side.

When using MauiCompatibility, during the lifecycle event OnLaunching, Microsoft.Maui.Controls.Compatibility.Forms.Init is called.

In this function, MauiContext.GetOptionalPlatformWindow (which is a wrapper around MauiContext.Services.GetService<Window>()) is used to try to generate a window to connect to. Since this is before the PlatformWindow is generated (that happens between OnLaunching and OnLaunched), the standard Maui IoC returns null. The Forms.Init code handles the null gracefully, does its setup and returns.

When using Prism, DryIoC does not return null in this case. It returns a Window, but that Window does not have a Native object, and thus throws a null reference error when trying to do just about anything, including check to see if the window is null.

Steps to Reproduce

  1. Create the Standard Prism Maui App (from Prism.Templates)
  2. Add MauiCompatibility()
  3. Run on Windows

Platform with bug

.NET MAUI

Affected platforms

Windows

Did you find any workaround?

The recommended solution in the previous issue was this:

#if WINDOWS10_0_17763_0_OR_GREATER
containerRegistry.RegisterInstance<Microsoft.UI.Xaml.Window>(Microsoft.UI.Xaml.Window.Current);
#endif

This didn't work for us, as Window.Current was null, and RegisterInstance didn't like that. Instead, we used the following, which let us run Prism and MauiCompatibility together:

#if WINDOWS10_0_17763_0_OR_GREATER
containerRegistry.RegisterSingleton<Microsoft.UI.Xaml.Window>();
#endif

However, when we used that, our app wouldn't close when we hit the X button on the window. There were still objects hanging out in memory, and I finally figured out it was because of the Forms.Init code hanging on to the singleton. Our current workaround is:

#if WINDOWS10_0_17763_0_OR_GREATER
containerRegistry.Register<Microsoft.UI.Xaml.Window>((provider)=>null);
#endif

This workaround mimics the standard Maui IoC of returning null for the window reference, and since Prism doesn't use that to generate it's PrismWindow everyone is happy. I'm not sure if this solution would still work if we were a multi-window app.

Relevant log output

No response

@dansiegel
Copy link
Member

I'm not really seeing this as a Prism issue and you haven't provided a sample to show me any reason to the contrary. You might try using the IWindowStateManager to get the current Window though.

@dansiegel dansiegel closed this as not planned Won't fix, can't repro, duplicate, stale Jul 4, 2024
@clnoel
Copy link
Author

clnoel commented Jul 8, 2024

What example do you need? Your own template fails to load when you add MauiCompatibility. It fails because of a null reference error. It has a null reference error because DryIoC returns an invalid Window when it is asked for one before CreatePlatformWindow is called, when it should be returning null (which does not generate a null reference error from the MauiCompatibility code). Isn't DryIoC part of the Prism project?

@dansiegel
Copy link
Member

@clnoel I have no idea what you're referring to. To be clear if you're using any templates on GitHub they aren't supported, only the templates on the private Commercial Plus feed are supported.

It has long been our policy, and it is specifically noted when you go to open a bug report that your issue will be closed without further consideration if you do not have a reproduction.

Screenshot 2024-07-07 at 7 06 29 PM

@clnoel
Copy link
Author

clnoel commented Jul 8, 2024

My apologies. I did assume the templates coming from this VS Extension were official. https://marketplace.visualstudio.com/items?itemName=BrianLagunas.PrismTemplatePack&ssr=false#overview

I have now made a demo app, at https://github.com/clnoel/DemoPrismMauiCompat

My example has three states, controlled by #define statements at the top of MauiProgram. Please use only one statement at a time when using my example code.

Under "BROKEN", the exception stack looks like this:
image

When I go into the decompiled Maui Code, I see this:
image
Note that it is failing in the OnLaunching event, which happens before CreatePlatformWindow

Tracing further up the call stack, I see this:
image
Here, we have a call to state.Context.GetOptionalPlatformWindow() (which is a wrapper around MauiContext.Services.GetService<Window>(), which is a dependency injection call.)

It took a great deal of tracing, but I determined that the default Maui dependency injection returned null from that call. (You can trace that yourself using the "NOPRISM" option.)

However, under DryIoC, what we get back is:
image
Note that, even though the Window exists, the NativeObject does not, and that is causing a whole slew of null reference errors when looking into this object, including not being able to check it for null.

My workaround substitutes null for the window object returned from MauiContext.Services.GetService<Window>() which lets this function pass.

--Christina

P.S. The link connected to the word "reproduction" in the "new bug" template doesn't actually go anywhere. I'm assuming it's supposed to connect to repo.md instead of repro.md ? or that repo.md is named wrong?

@dansiegel
Copy link
Member

Currently we are only providing Commercial Plus subscribers with templates.

I don't really see any harm in adding this work around for WinUI apps so the next public release should have it but in the mean time you can just add this to your app to work around the issue.

#if WINDOWS
#nullable disable
                        container.Register<Microsoft.UI.Xaml.Window>(r => r.Resolve<IWindowManager>()
                                .Windows
                                .FirstOrDefault()
                                ?.Handler
                                ?.PlatformView as Microsoft.UI.Xaml.Window);
#nullable restore
#endif

If you have a Commercial Plus license and are using a more recent build than what is publicly available on NuGet.org then you should replace the Windows.FirstOrDefault() with Current

@dansiegel dansiegel reopened this Jul 8, 2024
@stale stale bot removed wontfix labels Jul 8, 2024
@gmarbury
Copy link

I think this is the same issue as #3213. There is a link to a sample repo in there that reproduces the problem.

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

No branches or pull requests

3 participants