.NET MAUI中Shell传递ViewModel属性失败问题求助
.NET MAUI Shell导航QueryProperty为空的问题排查与解决
核心原因
你遇到的问题本质是时机不对:ViewModel的构造函数在实例化时立刻执行,但Shell的QueryProperty赋值操作是在ViewModel创建完成之后才进行的。所以你在构造函数里调用LoadAdvertAsync(Convert.ToInt32(AdvertId))时,AdvertId还没被赋值,自然为空。
解决方案
以下是几种可靠的解决方式,按需选择:
方式一:利用ObservableProperty的属性变更回调
借助CommunityToolkit.Mvvm的[ObservableProperty]特性,它会自动生成属性变更的回调方法,我们可以在这个回调里加载数据:
[QueryProperty("AdvertId", "AdvertId")] public partial class AdvertDetailsVM : ObservableObject { [ObservableProperty] public string advertId; private readonly IMyHttpClient _httpClient; public AdvertDetailsVM(IMyHttpClient httpClient) { _httpClient = httpClient; // 不要在构造函数里调用加载方法 } // 由ObservableProperty自动生成的属性变更触发方法 partial void OnAdvertIdChanged(string value) { if (!string.IsNullOrEmpty(value) && int.TryParse(value, out int advertId)) { // 此时AdvertId已经被赋值,可安全调用加载逻辑 LoadAdvertAsync(advertId); } } private async void LoadAdvertAsync(int advertId) { // 这里编写调用_httpClient加载广告详情的逻辑 } }
方式二:在页面OnAppearing事件中触发加载
如果不想依赖属性变更回调,可以把加载逻辑放到页面的OnAppearing方法中,此时QueryProperty已经完成赋值:
// 目标ContentPage代码 public partial class AdvertDetails : ContentPage { private readonly AdvertDetailsVM _vm; public AdvertDetails(AdvertDetailsVM vm) { InitializeComponent(); _vm = vm; BindingContext = vm; } protected override void OnAppearing() { base.OnAppearing(); if (!string.IsNullOrEmpty(_vm.AdvertId) && int.TryParse(_vm.AdvertId, out int id)) { _vm.LoadAdvertAsync(id); } } }
对应的ViewModel需要把LoadAdvertAsync改为可访问的方法:
[QueryProperty("AdvertId", "AdvertId")] public partial class AdvertDetailsVM : ObservableObject { [ObservableProperty] public string advertId; private readonly IMyHttpClient _httpClient; public AdvertDetailsVM(IMyHttpClient httpClient) { _httpClient = httpClient; } public async Task LoadAdvertAsync(int advertId) { // 加载逻辑 } }
方式三:直接使用int类型接收QueryProperty
你传递的参数是int类型,没必要转成string接收,可以直接用int类型定义属性,省去类型转换步骤:
[QueryProperty("AdvertId", "AdvertId")] public partial class AdvertDetailsVM : ObservableObject { [ObservableProperty] public int advertId; private readonly IMyHttpClient _httpClient; public AdvertDetailsVM(IMyHttpClient httpClient) { _httpClient = httpClient; } partial void OnAdvertIdChanged(int value) { if (value > 0) // 根据业务判断有效ID { LoadAdvertAsync(value); } } private async void LoadAdvertAsync(int advertId) { // 加载逻辑 } }
额外检查点
- 确保
AdvertDetails页面已在Shell路由中注册,比如在AppShell.xaml.cs中添加:Routing.RegisterRoute(nameof(AdvertDetails), typeof(AdvertDetails)); - 检查路由名称拼写:
nameof(AdvertDetails)必须和页面类名完全一致,避免大小写或拼写错误。
内容的提问来源于stack exchange,提问作者Zidd
相关产品推荐
相关产品推荐

