.NET MAUI自定义Window类触发MauiContext为空致命异常求助
处理.NET MAUI自定义Window时MauiContext为null的致命异常
问题场景
自定义MyWindow继承自Window,重写OnStopped和OnResumed通过WeakReferenceMessenger发送启停消息;在App.xaml.cs中重写CreateWindow返回传入MainPage的MyWindow实例。应用从后台恢复时触发致命异常:System.InvalidOperationException: MauiContext is null。
代码示例
public class Message : ValueChangedMessage<string> { public Message(string message) : base(message) { } } public class MyWindow : Window { public MyWindow() : base() { } public MyWindow(Page page) : base(page) { } protected override void OnStopped() { WeakReferenceMessenger.Default.Send(new Message("Stopped")); } protected override void OnResumed() { WeakReferenceMessenger.Default.Send(new Message("Resumed")); } } // App.xaml.cs中重写的方法 protected override Window CreateWindow(IActivationState activationState) { return new MyWindow(MainPage); }
异常栈信息
Fatal Exception: android.runtime.JavaProxyThrowable: System.InvalidOperationException: MauiContext is null. at Microsoft.Maui.Controls.Window.get_MauiContext() at Microsoft.Maui.Controls.Platform.AlertManager.Subscribe(Window window) at Microsoft.Maui.Controls.Platform.AlertManager.Subscribe() at Microsoft.Maui.Controls.Window.<>c__DisplayClass206_0.g__OnPageHandlerChanged|0(Object sender, EventArgs e) at Microsoft.Maui.Controls.Window.OnPageChanged(BindableObject bindable, Object oldValue, Object newValue) at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, Boolean silent) at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes) at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess) at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value) at Microsoft.Maui.Controls.Window.set_Page(Page value) at Microsoft.Maui.Controls.Window..ctor(Page page) at name.ViewModels.MyWindow..ctor(Page page) at name.App.CreateWindow(IActivationState activationState) at Microsoft.Maui.Controls.Application.Microsoft.Maui.IApplication.CreateWindow(IActivationState activationState) at Microsoft.Maui.Platform.ApplicationExtensions.CreatePlatformWindow(Activity activity, IApplication application, Bundle savedInstanceState) at Microsoft.Maui.MauiAppCompatActivity.OnCreate(Bundle savedInstanceState) at name.MainActivity.OnCreate(Bundle savedInstanceState) at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_(IntPtr , IntPtr , IntPtr ) at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V(_JniMarshal_PPL_V , IntPtr , IntPtr , IntPtr ) at crc64790243dcc0ae3d15.MainActivity.n_onCreate(MainActivity.java) at crc64790243dcc0ae3d15.MainActivity.onCreate(MainActivity.java:40) at android.app.Activity.performCreate(Activity.java:7994) at android.app.Activity.performCreate(Activity.java:7978) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1534) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3439) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3632) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2067) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7701) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
解决方案
根源分析
在Window构造函数中直接传入Page时,内部会触发PageHandlerChanged事件,此时Window的MauiContext尚未完成初始化,导致AlertManager订阅操作失败抛出异常。
方案1:延迟设置Page(推荐)
避免在构造函数中直接传入Page,改为在Window加载完成后再设置:
public class MyWindow : Window { public MyWindow() : base() { } public MyWindow(Page page) : base() { Loaded += (sender, args) => { if (Page == null) Page = page; }; } protected override void OnStopped() { WeakReferenceMessenger.Default.Send(new Message("Stopped")); } protected override void OnResumed() { WeakReferenceMessenger.Default.Send(new Message("Resumed")); } } // App.xaml.cs中修改CreateWindow protected override Window CreateWindow(IActivationState activationState) { // 每次创建新的MainPage实例,避免复用导致的状态异常 return new MyWindow(new MainPage()); }
方案2:通过HandlerChanged确保MauiContext可用
如果必须在构造时关联Page,可监听HandlerChanged事件,确保MauiContext初始化完成后再执行相关操作:
public class MyWindow : Window { public MyWindow(Page page) : base(page) { HandlerChanged += OnWindowHandlerChanged; } private void OnWindowHandlerChanged(object sender, EventArgs e) { if (Handler != null && MauiContext != null) { // 这里可以执行依赖MauiContext的初始化操作 HandlerChanged -= OnWindowHandlerChanged; // 移除监听避免重复触发 } } protected override void OnStopped() { WeakReferenceMessenger.Default.Send(new Message("Stopped")); } protected override void OnResumed() { WeakReferenceMessenger.Default.Send(new Message("Resumed")); } }
额外注意事项
- 应用后台恢复时,系统会重新调用
CreateWindow,不要复用App中提前初始化的MainPage静态实例,每次创建新的MainPage可以避免页面状态异常,同时减少MauiContext相关问题的触发概率。
内容的提问来源于stack exchange,提问作者devdennis
相关产品推荐
相关产品推荐

