英文:
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
注册的视图每次都会提供一个新的实例:
-
参见https://stackoverflow.com/a/72439742/199364,获取Maui的
IServiceProvider
并存储在App类中。希望将来会有一种标准的调用方法,以避免像这样捕获它。 -
或者按照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:
-
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. -
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>();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论