如何在多窗口的 MAUI 应用程序中注册视图?

huangapple go评论65阅读模式
英文:

How to register views in a multi-window MAUI application?

问题

You can resolve the "MauiContext is null" exception by not registering the view as a service and creating a new instance of the view every time a window is opened, as you've mentioned. This approach should work and is a common way to handle views in MAUI. Here's the relevant code:

Window newWindow = new()
{
    Page = new SubPage(),
};
Application.Current?.OpenWindow(newWindow);

This is a suitable approach for creating multiple instances of the SubPage view when opening multiple windows.

英文:

How do I correctly register a view that is used multiple times to open multiple windows?

Currently, I can only open a window that uses a view once.
The second time I attempt to open another window using the same view, I get this error:

System.InvalidOperationException: 'MauiContext is null.'

The relevant code looks like this:

public partial class SubPage : ContentPage
{
	public SubPage()
	{
		InitializeComponent();
	}
}

public partial class MainPage : ContentPage
{
	readonly SubPage subPage;

	public MainPage(SubPage subPage)
	{
		InitializeComponent();
		this.subPage = subPage;
	}

	private void OnNewWindowClicked(object sender, EventArgs e)
	{
		Window newWindow = new()
		{
			Page = this.subPage,
	 	};
		Application.Current?.OpenWindow(newWindow);
	}
}

The views are registered in MauiProgram.cs like so:

public static class MauiProgram
{
	public static MauiApp CreateMauiApp()
	{
		var builder = MauiApp.CreateBuilder();
		builder
			.UseMauiApp<App>()
			.Services
				.AddSingleton<MainPage>()
				.AddTransient<SubPage>();
		return builder.Build();
	}
}

Using this code, I can open a new window that uses SubPage, but the moment I try to open a second SubPage window, the MauiContext is null exception occurs.

I can "solve" the issue by not registering the view as a service, and instead creating a new instance of the view every time a window is opened. However, I am not sure if this is the right way to do things.

Window newWindow = new()
{
    Page = new SubPage(),
};
Application.Current?.OpenWindow(newWindow);

Any clues as to what I should be doing?

答案1

得分: 0

你不能在UI中同时在两个地方使用一个视图实例。(据我所知,在大多数(甚至所有?)层次结构的UI系统中都是如此,不仅仅是在Maui中。内部变量需要设置为特定位置。)

因此,在变量中存储subPage并重复使用它是一个错误。移除该变量。

  • 你的解决方法是一个解决方案,尽管显然没有使用你注册的服务。

  • 另一种方法是手动向服务请求一个实例;AddTransient注册的视图每次都会提供一个新的实例:

  1. 参见https://stackoverflow.com/a/72439742/199364,获取Maui的IServiceProvider并存储在App类中。希望将来会有一种标准的调用方法,以避免像这样捕获它。

  2. 或者按照Gerald在https://stackoverflow.com/a/72439035/199364中的模式进行操作;在页面中使用提供程序的DI,将提供程序存储在那里:

private IServiceProvider Provider;

public MainPage(IServiceProvider serviceProvider)
{
    Provider = serviceProvider;
}

... Provider.GetService<SubPage>();
英文:

You cannot use a view instance in two places simultaneously in the UI. (AFAIK, this is true in most (all?) hierarchical UI systems, not just Maui. Internal variables need to be set, specific to one location.)

Therefore, storing subPage in a variable and reusing it is an error. Remove that variable.

  • Your workaround is one solution, though it obviously isn't using the service you registered.

  • An alternative is to manually ask the service for an instance; AddTransient registration of the view then gives a new instance each time:

  1. See https://stackoverflow.com/a/72439742/199364 to get at Maui’s IServiceProvider and store in App class. Hopefully there will some day be a standard call, to avoid need to capture it like this.

  2. OR follow Gerald's pattern in https://stackoverflow.com/a/72439035/199364; use DI of provider in page, store the provider there:

private IServiceProvider Provider;

public MainPage(IServiceProvider serviceProvider)
{
    Provider = serviceProvider;
}

... Provider.GetService<SubPage>();

huangapple
  • 本文由 发表于 2023年4月17日 14:03:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76032094.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定