MAUI搜索页向Grid页面传递参数的技术实现问题
问题背景
刚接触MAUI,之前用WinForms习惯事件驱动开发,对MAUI的DI和MVVM模式摸不清。现在要实现:搜索页拿到参数后跳转到Grid页,通过API获取对应数据并在DevExpress DataGrid展示。已经搞定API和单页功能,但搜索页的AnimalParam参数传不到Grid页,Grid页的BindingContext在API调用前拿不到参数,试过非MVVM的按钮传参也没用,求正确的传参和API调用方案。
一、页面跳转传参(两种MVVM友好的方式)
方式1:构造函数直接传参(简单直接)
先改Grid页的构造函数,让它接收AnimalParam,再把参数传给ViewModel:
public partial class grdAnimal : ContentPage { public grdAnimal(AnimalParam param) { InitializeComponent(); // 拿到ViewModel并传入参数 var viewModel = (AnimalDataViewModel)BindingContext; viewModel.SearchParam = param; // 触发数据加载 _ = viewModel.LoadAnimals(); } }
然后改搜索页的跳转代码,传参过去:
async void OnSubmitClicked(Object sender, EventArgs e) { AnimalParam animalParm = new AnimalParam(); animalParm.AnimalName = "fred"; // 跳转时把参数传给Grid页 await Navigation.PushModalAsync(new grdAnimal(animalParm)); }
方式2:用NavigationParameter(适合复杂场景)
如果以后要传多个参数,或者想更贴合MAUI导航规范,用这个:
搜索页跳转代码:
async void OnSubmitClicked(Object sender, EventArgs e) { AnimalParam animalParm = new AnimalParam(); animalParm.AnimalName = "fred"; // 把参数打包进导航参数 var navParams = new Dictionary<string, object> { {"AnimalParam", animalParm} }; await Navigation.PushModalAsync(new grdAnimal(), navParams); }
Grid页在导航完成后接收参数:
protected override void OnNavigatedTo(NavigatedToEventArgs args) { base.OnNavigatedTo(args); // 解析导航参数 if (args.Parameter is Dictionary<string, object> navParams && navParams.TryGetValue("AnimalParam", out var paramObj) && paramObj is AnimalParam param) { var viewModel = (AnimalDataViewModel)BindingContext; viewModel.SearchParam = param; _ = viewModel.LoadAnimals(); } }
二、改造ViewModel,实现参数接收+异步API调用
原来的AnimalData要改成符合MVVM的ViewModel,实现INotifyPropertyChanged保证UI更新,同时把API调用改成异步(避免卡UI):
using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; namespace MauiAppPagesTest.AnimalViewModel { public class AnimalDataViewModel : INotifyPropertyChanged { private ObservableCollection<Animal> _animals; // 绑定给DataGrid的数据源 public ObservableCollection<Animal> Animals { get => _animals; set { _animals = value; OnPropertyChanged(); } } // 接收搜索参数 public AnimalParam SearchParam { get; set; } // 异步加载数据的方法 public async Task LoadAnimals() { // 参数为空直接返回 if (SearchParam == null || string.IsNullOrEmpty(SearchParam.AnimalName)) return; string apiUrl = "https://{你的有效API地址}/FindAnimalByName"; IRequestHandler requestHandler = new RestSharpRequestHandler(); // 用传入的参数调用API List<Animal> animalList = await requestHandler.GetAnimalByNameAsync(apiUrl, SearchParam.AnimalName); Animals = new ObservableCollection<Animal>(animalList); } // 实现INotifyPropertyChanged,让UI感知数据变化 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
注意:把你的
GetAnimalByName改成异步方法GetAnimalByNameAsync,MAUI里不能用同步API调用阻塞UI线程。
三、调整Grid页的初始化逻辑
原来的AnimalData构造函数里自动调用GenerateAnimal的逻辑要去掉,改成通过LoadAnimals手动触发,这样就能保证参数传入后再加载数据,解决BindingContext拿不到参数的问题。
Grid页的XAML不用大改,保持原来的BindingContext配置就行:
<ContentPage.BindingContext> <local:AnimalDataViewModel /> </ContentPage.BindingContext>
四、DI入门(逐步过渡到MVVM规范)
如果想进一步贴合MAUI的DI规范,把IRequestHandler注册到DI容器,避免手动new:
在MauiProgram.cs里添加注册代码:
builder.Services.AddSingleton<IRequestHandler, RestSharpRequestHandler>();
然后ViewModel的构造函数改成依赖注入:
private readonly IRequestHandler _requestHandler; // 构造函数注入IRequestHandler public AnimalDataViewModel(IRequestHandler requestHandler) { _requestHandler = requestHandler; } public async Task LoadAnimals() { // 用注入的实例调用API List<Animal> animalList = await _requestHandler.GetAnimalByNameAsync(apiUrl, SearchParam.AnimalName); Animals = new ObservableCollection<Animal>(animalList); }
这样代码解耦性更强,也符合MVVM的最佳实践。
内容的提问来源于stack exchange,提问作者Ken Mullins

