.NET MAUI CommunityToolkit.MVVM Shell传参TopicId为null问题
问题根因
你的代码存在两处核心逻辑错误,导致参数读取时为null:
- Shell的
[QueryProperty]路由参数赋值,发生在ViewModel构造函数执行完毕之后。你在构造函数中直接调用LoadQuestions()时,Shell还未完成参数到属性的映射,此时读取TopicId必然是空值。 - 你没有监听参数赋值完成的时机,参数被注入后没有触发加载逻辑。
修复步骤
- 移除构造函数中对
LoadQuestions()的调用,避免在参数未注入时提前执行依赖参数的逻辑。 - 利用CommunityToolkit.MVVM为
[ObservableProperty]字段自动生成的属性变更回调,在TopicId被赋值后再执行数据加载。
修正后的QuestionsPageViewModel核心代码如下:
[INotifyPropertyChanged] [QueryProperty(nameof(TopicId), nameof(TopicId))] public partial class QuestionsPageViewModel { public ObservableRangeCollection<Question> QuestionsList { get; set; } = new(); [ObservableProperty] string? title; [ObservableProperty] public string topicId; public QuestionsPageViewModel() { // 构造函数中不再调用LoadQuestions } // 源生成器自动识别的属性变更回调,TopicId赋值完成后自动执行 partial void OnTopicIdChanged(string value) { if (!string.IsNullOrWhiteSpace(value)) { LoadQuestions(); } } async void LoadQuestions() { Title = Utilities.ConvertTopicIdToString(short.Parse(TopicId)); try { using (var context = new DataContext()) { QuestionPack questionPack = context.QuestionPacks .First(x => x.TopicId == short.Parse(TopicId)); var questions = JsonConvert.DeserializeObject<List<Question>>(questionPack.Questions); QuestionsList.AddRange(questions); } } catch (Exception ex) { await Shell.Current.DisplayAlert("Error", $"Something went wrong: {ex}", "Cancel"); } } }
额外校验项
如果修改后仍无法获取参数,检查路由注册是否正确:
在MauiProgram.cs的构建逻辑中确认已添加路由注册代码,若未注册导航本身会抛出异常,可优先排除该问题:
Routing.RegisterRoute(nameof(QuestionsPage), typeof(QuestionsPage));
除了使用属性变更回调的方式,也可以在QuestionsPage的页面后置代码中重写
OnNavigatedTo生命周期方法,在导航完成后调用ViewModel的加载逻辑,效果完全一致。
内容的提问来源于stack exchange,提问作者Tanaka Mawere
相关产品推荐
相关产品推荐

