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

如何通过AddTransient服务在.NET MAUI MVVM页面间传值

.NET MAUI CommunityToolkit MVVM 页面间传参(无需QueryProperty)

问题原因分析

你之前用ServiceHelper获取Page2ViewModel实例传值后页面绑定的VM为Null,核心原因是:你提前获取的VM实例和Page2导航时自动创建的VM实例不是同一个(因为注册的是Transient服务,每次获取都会生成新实例),导致传值的实例和页面绑定的实例脱节。

可行解决方案

方案1:构造函数传参(推荐,符合依赖注入规范)

这种方式直接在创建ViewModel时传入参数,确保页面绑定的实例就是已赋值的实例。

  1. 修改Page2ViewModel的构造函数,接收ID参数:
public class Page2ViewModel : ObservableObject
{
    private int _id;
    public int Id
    {
        get => _id;
        set => SetProperty(ref _id, value);
    }

    // 带参数的构造函数
    public Page2ViewModel(int id)
    {
        _id = id;
    }
}
  1. 在MauiProgram中注册带参数的ViewModel工厂:
// 注册可传入ID的ViewModel工厂
builder.Services.AddTransient<Func<int, Page2ViewModel>>(sp => id => new Page2ViewModel(id));
// 同时保留基础注册(可选,根据导航方式调整)
builder.Services.AddTransient<Page2ViewModel>(sp => new Page2ViewModel(0));
  1. 在Page1ViewModel中通过工厂创建VM并导航:
public class Page1ViewModel : ObservableObject
{
    private readonly INavigationService _navigationService;
    private readonly IServiceProvider _serviceProvider;

    public RelayCommand<int> NavigateToPage2Command { get; }

    public Page1ViewModel(INavigationService navigationService, IServiceProvider serviceProvider)
    {
        _navigationService = navigationService;
        _serviceProvider = serviceProvider;
        NavigateToPage2Command = new RelayCommand<int>(NavigateToPage2);
    }

    private void NavigateToPage2(int id)
    {
        // 通过工厂创建带ID的Page2ViewModel
        var vmFactory = _serviceProvider.GetRequiredService<Func<int, Page2ViewModel>>();
        var page2Vm = vmFactory(id);
        
        // 创建Page2并绑定ViewModel
        var page2 = new Page2 { BindingContext = page2Vm };
        
        // 执行导航
        _navigationService.PushAsync(page2);
    }
}

方案2:页面生命周期传参

通过页面的导航事件获取参数,直接传递给绑定的ViewModel。

  1. Page1ViewModel导航时携带参数:
private void NavigateToPage2(int id)
{
    var navParams = new Dictionary<string, object> { { "TargetId", id } };
    _navigationService.PushAsync(nameof(Page2), navParams);
}
  1. 在Page2的后台代码中接收参数并传递给ViewModel:
protected override void OnNavigatedTo(NavigatedToEventArgs args)
{
    base.OnNavigatedTo(args);
    if (args.Parameter is Dictionary<string, object> parameters && 
        parameters.TryGetValue("TargetId", out var idObj) && 
        idObj is int targetId)
    {
        if (BindingContext is Page2ViewModel vm)
        {
            vm.Id = targetId;
            // 若有初始化方法可直接调用:vm.Initialize(targetId);
        }
    }
}

方案3:消息传递(CommunityToolkit自带)

利用WeakReferenceMessenger实现跨ViewModel的参数传递,适合完全解耦的场景。

  1. 定义消息类:
public class IdTransferMessage : ValueChangedMessage<int>
{
    public IdTransferMessage(int value) : base(value) { }
}
  1. Page1ViewModel发送消息并导航:
private void NavigateToPage2(int id)
{
    WeakReferenceMessenger.Default.Send(new IdTransferMessage(id));
    _navigationService.PushAsync(nameof(Page2));
}
  1. Page2ViewModel接收消息并赋值:
public class Page2ViewModel : ObservableObject
{
    private int _id;
    public int Id
    {
        get => _id;
        set => SetProperty(ref _id, value);
    }

    public Page2ViewModel()
    {
        // 注册消息监听
        WeakReferenceMessenger.Default.Register<IdTransferMessage>(this, (recipient, message) =>
        {
            Id = message.Value;
        });
    }

    // 销毁时注销监听,避免内存泄漏
    ~Page2ViewModel()
    {
        WeakReferenceMessenger.Default.Unregister<IdTransferMessage>(this);
    }
}

内容的提问来源于stack exchange,提问作者przepiora87

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 00:00:18