.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
相关产品推荐
相关产品推荐

