.NET MAUI Shell导航传参后自动填充页面数据实现方案
问题原因
你在OnNavigatedTo中调用命令失败的核心原因是页面类声明的FieldPerformanceViewModel viewModel字段从未被赋值,始终为null:
- 构造函数中你虽然接收了依赖注入传入的ViewModel实例,也将其赋值给了
BindingContext,但没有把这个实例保存到类级别的viewModel字段中 - 后续执行
OnNavigatedTo时,访问null对象的GetFieldPerformanceCommand会触发空引用异常,命令自然无法执行
方案1:快速修复(仅修改页面后台代码)
只需要在构造函数中把传入的ViewModel实例赋值给类字段即可,Shell给[QueryProperty]标注的属性赋值的时机早于OnNavigatedTo执行,此时导航参数已经完成赋值,执行命令可以正常取到所需字段。
修正后的页面后台代码如下:
public partial class FieldPerformancePage : ContentPage { private readonly FieldPerformanceViewModel _viewModel; public FieldPerformancePage(FieldPerformanceViewModel viewModel) { InitializeComponent(); // 同时给BindingContext和类字段赋值 BindingContext = _viewModel = viewModel; } protected override void OnNavigatedTo(NavigatedToEventArgs args) { base.OnNavigatedTo(args); _viewModel.GetFieldPerformanceCommand.Execute(null); } }
方案2:MVVM最优解(完全移除页面后台调用逻辑)
不需要依赖页面生命周期方法,直接利用CommunityToolkit.Mvvm源生成器提供的属性变更回调,在导航参数被赋值后自动触发数据加载,彻底解耦页面和ViewModel的逻辑,更符合MVVM设计规范。
仅需修改ViewModel代码,给FieldAssignedWbs属性添加值变更回调即可:
namespace TrackMate.ViewModels; [QueryProperty(nameof(FieldAssignedWbs), nameof(FieldAssignedWbs))] public partial class FieldPerformanceViewModel : BaseViewModel { [ObservableProperty] FieldAssignedWbs fieldAssignedWbs; [ObservableProperty] FieldPerformance fieldPerformance; private readonly FieldPerformanceService _fieldPerformanceService; public FieldPerformanceViewModel(FieldPerformanceService fieldStatusService) { Title = "Status"; _fieldPerformanceService = fieldStatusService; } // 源生成器自动识别的属性变更回调,FieldAssignedWbs赋值完成后自动执行 partial void OnFieldAssignedWbsChanged(FieldAssignedWbs value) { if (value != null) { GetFieldPerformanceCommand.Execute(null); } } [ICommand] async Task GetFieldPerformanceAsync() { if (IsBusy || FieldAssignedWbs == null) return; try { IsBusy = true; int wbsId = FieldAssignedWbs.WbsId; var fieldPerformanceList = await _fieldPerformanceService.GetFieldPerformanceList(wbsId); if (fieldPerformanceList.Count != 0) FieldPerformance = fieldPerformanceList.First(); } catch (Exception ex) { Debug.WriteLine(ex); await Shell.Current.DisplayAlert("错误!", $"无法加载记录:{ex.Message}", "确定"); } finally { IsBusy = false; } } }
修改完成后页面后台不需要保留任何命令调用逻辑,仅保留基础初始化即可:
public partial class FieldPerformancePage : ContentPage { public FieldPerformancePage(FieldPerformanceViewModel viewModel) { InitializeComponent(); BindingContext = viewModel; } }
内容的提问来源于stack exchange,提问作者Todd T
相关产品推荐
相关产品推荐

