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

.NET Maui UI独立MVVM架构下跨视图传对象问题求助

问题分析与解决方案

一、跨视图传递Order对象失败的修复

1. 修正OrdersViewModel中的命令参数错误

当前GoToOrdersCommand的委托错误传入了类成员_order(空对象),而非点击事件传递的参数order,导致传递的Order始终为空:
原代码:

GoToOrdersCommand = new RelayCommand<Order>((order) => OrderDetails(_order));

修改为:

GoToOrdersCommand = new RelayCommand<Order>((order) => OrderDetails(order));

2. 完善RelayCommand的泛型实现

当前泛型RelayCommand未实际使用泛型参数,仍依赖Action<object>,容易引发类型转换问题,改为强类型实现:

namespace Orders.Common.ViewModel.Command
{
    // 带参数的RelayCommand
    public class RelayCommand<T> : ICommand
    {
        private readonly Action<T> _execute;
        private readonly Func<T, bool> _canExecute;

        public RelayCommand(Action<T> execute, Func<T, bool> canExecute = null)
        {
            _execute = execute ?? throw new ArgumentNullException(nameof(execute));
            _canExecute = canExecute;
        }

        public event EventHandler CanExecuteChanged;

        public void RaiseCanExecuteChanged()
        {
            CanExecuteChanged?.Invoke(this, EventArgs.Empty);
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute((T)parameter);
        }

        public void Execute(object parameter)
        {
            _execute((T)parameter);
        }
    }

    // 无参数的RelayCommand
    public class RelayCommand : ICommand
    {
        private readonly Action _execute;
        private readonly Func<bool> _canExecute;

        public RelayCommand(Action execute, Func<bool> canExecute = null)
        {
            _execute = execute ?? throw new ArgumentNullException(nameof(execute));
            _canExecute = canExecute;
        }

        public event EventHandler CanExecuteChanged;

        public void RaiseCanExecuteChanged()
        {
            CanExecuteChanged?.Invoke(this, EventArgs.Empty);
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute();
        }

        public void Execute(object parameter)
        {
            _execute();
        }
    }
}

3. 让OrderViewModel接收导航参数

在OrderPage的后台代码中,通过Shell导航参数获取Order并传递给ViewModel:

[QueryProperty(nameof(SelectedOrder), "Order")]
public partial class OrderPage : ContentPage
{
    public Order SelectedOrder
    {
        set
        {
            if (BindingContext is OrderViewModel vm)
            {
                vm.Order = value;
            }
        }
    }

    public OrderPage(OrderViewModel viewModel)
    {
        InitializeComponent();
        BindingContext = viewModel;
    }
}

二、DelegateCommand与RelayCommand的合并建议

DelegateCommand和RelayCommand都是ICommand的实现,功能重叠,无需同时保留。统一使用RelayCommand即可,通过泛型区分带参数/无参数场景:

  • 无参数操作:使用RelayCommand类
  • 带参数操作:使用RelayCommand<T>类

修改OrderViewModel中的SaveCommand为RelayCommand:

public RelayCommand SaveCommand { get; }

public OrderViewModel()
{
    _order = new Order() { OrderID = -1, Customer = "", OrderDate = DateTime.Now };
    SaveCommand = new RelayCommand(Save, () => CanSave);
}

public OrderViewModel(Order order)
{
    _order = order;
    SaveCommand = new RelayCommand(Save, () => CanSave);
}

额外配置说明

确保MauiProgram.cs中正确注册依赖项:

builder.Services.AddSingleton<IOrderNavigation, OrderNavigationService>();
builder.Services.AddTransient<OrdersViewModel>();
builder.Services.AddTransient<OrderViewModel>();
builder.Services.AddTransient<OrdersPage>();
builder.Services.AddTransient<OrderPage>();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 04:10:32