MAUI中如何传递查询参数至ViewModel并调用GetMovies方法?
解决MAUI中AppShell查询参数传递后ViewModel无法获取值的问题
你的问题核心在于:AppShell的QueryProperty赋值逻辑是在ViewModel构造函数执行完成后才触发的,所以在构造函数里直接访问SelectedGenre必然是null。
下面是具体的修复方案:
1. 利用CommunityToolkit.Mvvm的属性变更回调触发数据加载
因为你用了[ObservableProperty]标记selectedGenre,框架会自动生成名为OnSelectedGenreChanged的部分方法。我们可以重写这个方法,在SelectedGenre被赋值(也就是查询参数传递完成)时自动调用GetMovies。
修改后的ViewModel代码:
using System; using System.Collections.ObjectModel; using System.Diagnostics; using CommunityToolkit.Mvvm.ComponentModel; using TimesNewsApp.Models; using TimesNewsApp.Services; namespace TimesNewsApp.ViewModels { [QueryProperty(nameof(SelectedGenre), nameof(SelectedGenre))] public partial class MovieListGenrePageViewModel : BaseViewModel { public ObservableCollection<Result> Movie { get;} = new(); [ObservableProperty] private Genre selectedGenre; NewsApiManager apiService; public Command GetMovieComand { get; } public MovieListGenrePageViewModel(NewsApiManager apiService) { this.apiService = apiService; // 移除构造函数中调用GetMovies的代码 } // 重写自动生成的属性变更回调方法 partial void OnSelectedGenreChanged(Genre oldValue, Genre newValue) { // 当查询参数赋值完成后,调用加载方法 _ = GetMovies(newValue); } async Task GetMovies(Genre selectedGenre) { if (IsBusy) return; try { IsBusy = true; if (selectedGenre == null) return; var movies = await apiService.GetMovieByGenre(selectedGenre.Id); if (Movie.Count != 0) return; foreach (var item in movies.results) Movie.Add(item); } catch (Exception ex) { Debug.WriteLine($"Unable to get movie: {ex.Message}"); await Application.Current.MainPage.DisplayAlert("Error!", ex.Message, "OK"); } finally { IsBusy = false; } } } }
2. 确保导航时参数传递正确
在发起导航的页面,要保证传递的Genre对象是可被MAUI序列化的(比如属性都是公共可访问的,或者给Genre类标记[Serializable])。导航代码示例:
// 示例:在Genre列表选中后的导航逻辑 async Task OnGenreSelected(Genre selectedGenre) { if (selectedGenre == null) return; await Shell.Current.GoToAsync(nameof(MovieListGenrePage), new Dictionary<string, object> { { nameof(MovieListGenrePageViewModel.SelectedGenre), selectedGenre } }); }
额外注意事项
- 永远不要在ViewModel构造函数中依赖QueryProperty的值,因为此时参数还未完成传递
- 如果需要手动触发数据加载(比如下拉刷新),可以保留
GetMovieComand,在Command中直接调用GetMovies(SelectedGenre) - 确保
BaseViewModel中的IsBusy属性正确实现了INotifyPropertyChanged(如果用[ObservableProperty]标记,框架会自动处理)
内容的提问来源于stack exchange,提问作者Toby Nwude
相关产品推荐
相关产品推荐

