1

我们的新项目从 View first 模式开始,使用 ViewModelLocator 将视图与视图模型结合起来。

我想更改为 ViewModel 第一模式。

这是我的视图模型构造函数:

public DeviceSelectionViewModel(IDataModel dataModel, IMessenger messenger)
{
    if (dataModel == null) throw new ArgumentNullException("dataModel");
    if (messenger == null) throw new ArgumentNullException("messenger");

    Selector = new PlantDataTemplateSelector();
    PlantSelector = new PlantNodesSelector();
    Plants = new List<Plant>(0);

    messenger = messenger;
    messenger.Register<PlantDataLoadedMessage>(this, m => DispatcherHelper.CheckBeginInvokeOnUI(() => OnPlantDataLoaded(m.Plants)));

    RefreshData(_dataModel);
}

下面是我现在如何首先使用 ViewModel 选择合适的 ViewModel。

public class MainViewModel : Module
{

    public MainViewModel()
    {
        SelectedView = new DeviceSelectionViewModel();
    }

    public ViewModelBase SelectedView { get; set; }

}

首先使用 View,我从未通过代码直接调用 ViewModel,因此构造函数依赖注入工作正常。

现在我通过控制器 ViewModel 调用 ViewModel,它需要 ViewModel 构造函数的 2 个参数。

在控制器视图模型中保存引用并将它们传递给构造函数是否正确?我在这里遗漏了一些关于 DI 在这种情况下如何工作的东西?

我仍然将这些部分与 DI(Ninject) 和 MVVM 放在一起,所以请善待:)

4

1 回答 1

1

我们有同样的问题。

您有以下选择:

  • MainViewModel创建DeviceViewModel提供所需参数的值
  • MainViewModel已经解决了DeviceViewModel

DeviceViewModel第一个变体在仅针对 View 绑定公开的情况下增加耦合。如果MainViewModel与之通信,DeviceViewModel那么耦合已经隐含,除非通过某个接口MainViewModel看到DeviceViewModel不可避免地需要第二个选项。

第一种方法的另一个问题是,在某些情况下,嵌套 VM 可能需要更多值来创建它,因为父 VM 需要。
这可以通过扩展父 VM 构造函数以包含这些附加参数来解决。但是当(尽管从未在实践中)构建复杂的虚拟机图时,根虚拟机的构造函数可能会变得臃肿。

我们现在有两种选择。

我们所有的 ViewModel 都继承自ViewModelBase抽象类。它有几个重载的构造函数,其中大多数IViewModelFactory作为输入。所以我们可以要求工厂创造我们的ViewModel需求。Wee 决定不担心返回的类型,只返回创建的 ViewModel 的类型,只封装它的创建。所以这不是真正的DI。

我们也使用 Messanger,但我们的 ViewModel 不能显式发送消息,只能订阅消息。我们故意这样做是为了限制特定 VM 可以发送(甚至订阅)的一组消息。

于 2013-01-17T23:17:31.860 回答