.NET MAUI ViewModel查询参数传递及QueryProperty赋值后GetMovies方法参数为空问题排查
分析与解决方案
你遇到的核心问题是调用GetMovies()的时机不对,再加上几个细节没处理到位,导致SelectedGenre在方法执行时还是空值。咱们一步步拆解修复:
1. 为什么SelectedGenre为空?
.NET MAUI的[QueryProperty]特性是在ViewModel实例化完成之后才会把导航参数赋值到对应属性上的。你现在在构造函数里直接调用Task.Run(async () => await GetMovies(SelectedGenre)),这时候ViewModel刚创建,QueryProperty还没来得及传递参数,所以SelectedGenre自然是null。
2. 修复步骤
步骤1:在SelectedGenre属性变更时触发数据加载
把数据加载逻辑移到SelectedGenre的属性setter里,当参数被赋值后立刻触发GetMovies():
public Genre SelectedGenre { get => selectedGenre; set { if (SetProperty(ref selectedGenre, value)) { // 属性变更成功后,加载对应分类的电影 _ = GetMovies(); // 用下划线忽略返回Task,避免构造函数异步问题 } } }
步骤2:移除构造函数里的过早调用
删掉构造函数里的Task.Run代码,同时确保GetMovieCommand绑定正确的加载逻辑:
public MovieListGenrePageViewModel(NewsApiManager apiService) { this.apiService = apiService; GetMovieComand = new Command(async () => await GetMovies()); }
步骤3:修正GetMovies()的参数与硬编码问题
你当前的GetMovies()里硬编码了27作为分类ID,完全没用到传入的SelectedGenre,这会导致不管传什么分类都加载同一批电影。修改方法如下(假设你的Genre类有Id属性,根据实际结构调整):
async Task GetMovies() { if (IsBusy || SelectedGenre == null) return; try { IsBusy = true; // 使用SelectedGenre的实际ID调用接口 Movie 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; } }
步骤4:检查导航传参的正确性
确保你在跳转到MovieListGenrePage时,正确传递了SelectedGenre参数,示例代码如下:
// 从其他页面导航时的代码示例 await Shell.Current.GoToAsync(nameof(MovieListGenrePage), new Dictionary<string, object> { { nameof(MovieListGenrePageViewModel.SelectedGenre), selectedGenreInstance } });
3. 额外优化建议
- 避免在构造函数里用
Task.Run执行异步代码,构造函数不支持异步,这种写法容易引发不可预测的行为。 - 如果需要支持下拉刷新或手动重新加载,你的
GetMovieCommand可以直接绑定到页面的刷新控件或按钮上。
内容的提问来源于stack exchange,提问作者Toby Nwude
相关产品推荐
相关产品推荐

