You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 20:36:18