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

时间:2015-12-25 02:59:55

标签: c# object mvvm constructor-injection

我需要将一个对象从一个视图模型传递给另一个视图模型。在我当前的实现中,我创建了一个ProductVM的静态实例,遵循此example,然后从实例访问它的属性。但是从长远来看,传递静态实例似乎并不是一个可靠的设计。

private static ProductVM _instance = new ProductVM();
public static ProductVMInstance { get { return _instance; } }

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

问题:

有没有人有任何关于如何实现ctor注入传递对象的例子? (最好不要使用第三方框架)

ProductsVM:(查看包含要发送的属性的模型)

    public ProductModel SelectedProduct { get; set; }

CustomerOrdersVM:(查看需要传递SelectedProduct的模型)

public class CustomerOrdersViewModel : IPageViewModel
{

    public CustomerOrdersViewModel()
    {                  

    }
}

2 个答案:

答案 0 :(得分:2)

Rowbear报道了EventAggregators的情况。它们无法在所有情况下使用。

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

这不适用于在显示ViewModel / View之前必须实例化/导航的情况。一个例子是智能手机应用程序,您可以在其中点击产品并接收它的详细信息或类似内容。

在这种情况下,您需要一个导航服务,您可以将某个参数(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框架(最初由Microsoft开发)

答案 1 :(得分:1)

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

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(大多数)项目,该项目使用构造函数注入而没有第三方注入器。这是有道理的,因为我们有一个包含多个视图模型作为其属性的首要对象(它在主要的父视图模型和技术上的注入器)。然而,它最终变得有点笨拙,因为一些视图模型在其构造函数中需要一个看似随机的其他视图模型。根据视图模型与模型或数据库/外部服务的完全分离程度,单元测试视图模型也可能变得更加困难,因为您可能在视图模型中开始需要使用生产数据完全构造依赖项的逻辑。 p>

这让我问你......为什么你需要CustomerOrderVM中的SelectedProduct?是因为用户交互会在ProductsVM中设置SelectedProduct属性,而您的CustomerOrdersVM需要知道它吗?如果是这种情况,您是否考虑过实施EventAggregator Pattern?当我团队中的某个人实现了这一点时,它使视图模型之间的信息传递变得轻而易举。视图模型将引用eventaggregator,并在构造时订阅事件。这样,当您的用户选择产品时,您的ProductsVM可以执行操作,并发布您的CustomerOrdersVM可以订阅并对其执行操作的事件。