如何使用依赖注入将对象传递给 ViewModel?

How to pass an object to a ViewModel using dependency injection?

我需要将对象从一个视图模型传递到另一个视图模型。在我当前的实现中,我创建了一个 ProductVM 的静态实例,在这个 example 之后,然后从实例 属性 访问它。但是在长 运行.

中传递静态实例似乎并不是一个可靠的设计
private static ProductVM _instance = new ProductVM();
public static ProductVMInstance { get { return _instance; } }

在研究提供静态视图模型实例的替代方案时,我发现 constructor injection 作为一个选项。

问题:

有没有人有关于如何为传递对象实施构造函数注入的示例? (最好不用第三方框架)

ProductsVM:(保存 属性 待发送的视图模型)

    public ProductModel SelectedProduct { get; set; }

CustomerOrdersVM:(SelectedProduct 需要传入的视图模型)

public class CustomerOrdersViewModel : IPageViewModel
{

    public CustomerOrdersViewModel()
    {                  

    }
}

您提供的 example link 中接受的答案实际上描述了构造函数注入。答案 1 和 2 都在技术上描述 "constructor injection"。为了在没有第三方框架的情况下为您的案例实现构造函数注入,您基本上需要将 SelectedProduct 或 ProductsVM 实例传递给 CustomerOrdersVM 的构造函数。唯一剩下的是一个总体 class 或用作 "injector" 的视图模型,它控制 CustomerOrdersVM 实例和 ProductsVM 实例的构造(或者至少有一个实例的引用,它可以传递到 CustomerOrdersVM 的 ctor):

public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {
        ProductsViewModel = new ProductsVM();
        OrdersViewModel = new CustomerOrdersVM(ProductsViewModel);
    }
    public CustomerOrdersVM OrdersViewModel { get; private set; }

    public ProductsVM ProductsViewModel { get; private set; }
}

我参与了一个 MVVM(大部分)项目,该项目始终使用构造函数注入而没有第三方注入器。这是有道理的,因为我们有一个包含多个视图模型作为其属性的总体对象(从技术上讲,它充当主要的父视图模型和注入器)。然而,它最终变得有些笨拙,因为一些视图模型在其构造函数中需要一个看似随机的其他视图模型。根据您的视图模型与您的模型或 databases/external 服务的分离程度,对视图模型进行单元测试也可能变得更加困难,因为您可能开始在视图模型中包含逻辑,需要使用生产数据完全构建依赖关系。

这让我问你...为什么你需要 CustomerOrderVM 中的 SelectedProduct?是因为用户交互将在 ProductsVM 中设置 SelectedProduct 属性,而您的 CustomerOrdersVM 需要了解它吗?如果是这样,您是否考虑过实施 EventAggregator Pattern?当我团队中的某个人实施此功能时,它使视图模型之间的信息传递变得轻而易举。视图模型将引用事件聚合器,并在构造时订阅事件。这样,当您的用户选择产品时,您的 ProductsVM 可以采取行动,并发布您的 CustomerOrdersVM 可以订阅并采取行动的事件。

Rowbear 介绍了 EventAggregators 的案例。它们不能在所有情况下使用。

EventAggregator 模式仅在目标 ViewModel(及其对应的视图)已经实例化时才有用,因为只有这样 ViewModel 才会注册到事件以对其做出反应。

这不适用于 ViewModel/View 必须也是 instantiated/navigated 才能显示的情况。一个例子是智能手机应用程序,您可以在其中单击产品并接收其详细信息或类似信息。

在这种情况下,您需要一个导航服务,您可以在其中将某个参数(productIdorderId 等)传递给导航调用,例如 navigationService.Navigate("OrderDetails", orderId); 并让您的ViewModel 实现了某种 INavigationAware 接口,如果 ViewModel 实现了该接口,导航服务会调用该接口。

public class OrderDetailsViewModel : ViewModelBase, INavigationAware
{
    public async void OnNavigatedFrom(object parameter) 
    {
        var orderId = (int)parameter;
        var order = await orderRepository.GetOrderByIdAsync(orderId);

        // display your order in the ViewModel here
    }
}

导航服务自带的框架有很多,最受企业应用欢迎的是Prism MVVM框架(最初由微软开发)