如何检测MAUI中PageLoaded与ModelLoaded状态?
我逐行排查代码定位错误,但情况逐渐复杂失控,因此想找测试PageLoaded && ModelLoaded的方法,但不知道具体操作方式。
我有一个绑定C# Model的Xaml页面,代码如下:
using CommunityToolkit.Maui.Views; using NameProject.Models; namespace NameProject.Pages; public partial class AlertPage : Popup { AlertModel alertmodel; public AlertPage(AlertModel alertmodel) { InitializeComponent(); BindingContext = alertmodel; this.alertmodel = alertmodel; alertmodel.Alertpage = this; } }
Model中有int[]类型的Indexcontrol属性,每次创建Xaml页面时都会传入值,确保不为空,代码如下:
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using NameProject.Pages; namespace NameProject.Models { public partial class AlertModel : ObservableObject { public AlertModel() => test(); void test() { //await Task.Delay(2000); //if (Indexcontrol != null) //{ foreach (int item in Indexcontrol) { if (item == 1) Showcontrolred = true; } //} //else return; } [ObservableProperty] private int[]? indexcontrol; [ObservableProperty] private AlertPage? alertpage; } }
核心问题
Model构造函数执行时无法获取Indexcontrol的值,抛出System.NullReferenceException: 'Object reference not set to an instance of an object.'。
取消注释Task.Delay(2000)并改为async Task可临时解决,但加载耗时超过2000毫秒就会失效,而且我不想用异步方法,仅把它作为临时调试手段。
尝试检测PageLoaded状态但操作繁琐,在Model构造函数中声明PageLoaded函数也引发错误。现在需要最优且简便的方法,在Model中同时检测PageLoaded和ModelLoaded状态。
解决方案
1. 调整初始化逻辑,构造时传入Indexcontrol
直接修改Model构造函数,将Indexcontrol作为必填参数传入,确保构造执行时就能拿到有效值,无需等待页面加载:
public partial class AlertModel : ObservableObject { // 修改构造函数,接收Indexcontrol参数 public AlertModel(int[] indexcontrol) { Indexcontrol = indexcontrol; test(); } void test() { foreach (int item in Indexcontrol) { if (item == 1) Showcontrolred = true; } } [ObservableProperty] private int[] indexcontrol; // 去掉?,因为构造时必传非空值 [ObservableProperty] private AlertPage? alertpage; }
创建页面时先构造Model并传入参数:
// 假设已有初始化好的int[] indexData var alertModel = new AlertModel(indexData); var alertPage = new AlertPage(alertModel);
2. 利用ObservableProperty的属性变更回调
如果必须保留原有构造方式,可借助CommunityToolkit.Mvvm的自动生成回调特性,在Indexcontrol和Alertpage都赋值完成后触发逻辑:
public partial class AlertModel : ObservableObject { public AlertModel() { } void test() { foreach (int item in Indexcontrol) { if (item == 1) Showcontrolred = true; } } [ObservableProperty] private int[]? indexcontrol; // Indexcontrol属性变更时触发的自动生成方法 partial void OnIndexcontrolChanged(int[]? oldValue, int[]? newValue) { // 同时检查页面是否已关联 if (newValue != null && Alertpage != null) { test(); } } [ObservableProperty] private AlertPage? alertpage; // 页面赋值后也检查一次 partial void OnAlertpageChanged(AlertPage? oldValue, AlertPage? newValue) { if (newValue != null && Indexcontrol != null) { test(); } } }
这种方式会在两个依赖条件都满足时自动执行test,无需手动监听页面事件。
3. 绑定页面Loaded事件到Model命令
如果需要严格依赖页面加载完成,可在XAML中把页面Loaded事件绑定到Model的命令:
首先在Model中添加RelayCommand:
public partial class AlertModel : ObservableObject { [RelayCommand] void OnPageLoaded() { if (Indexcontrol != null) { test(); } } // 其他代码不变... }
然后在AlertPage的XAML中绑定事件:
<ct:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:ct="clr-namespace:CommunityToolkit.Maui.Views;assembly=CommunityToolkit.Maui" x:Class="NameProject.Pages.AlertPage" Loaded="{Binding OnPageLoadedCommand}"> <!-- 页面内容 --> </ct:Popup>
此方法确保页面加载完成后再执行逻辑,同时Model内可检查Indexcontrol是否就绪。
内容的提问来源于stack exchange,提问作者Hưng Nguyễn

