2013-01-17 50 views
1

我们的新项目始于使用ViewModelLocator与ViewModel结合视图的View第一个模式。从视图优先改变为视图模型优先 - 我如何处理构造函数依赖注入

我想更改为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); 
} 

下面是我现在首先用视图模型选择适当的视图模型。

public class MainViewModel : Module 
{ 

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

    public ViewModelBase SelectedView { get; set; } 

} 

随着视图第一,我从来没有直接通过代码直接调用ViewModel,所以构造函数依赖注入工作正常。

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

在这里适当的玩法是在控制器视图模型中保存引用并将它们传递给构造函数?在这种情况下,我错过了一些关于DI如何工作的内容?

我仍与DI(Ninject)和MVVM把拼在一起,所以要那种:)

回答

1

我们有同样的问题。

您有以下选择:

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

第一个变种增加耦合的情况下DeviceViewModel仅适用于View绑定。如果MainViewModelDeviceViewModel通信,那么耦合已暗示,除非MainViewModel通过某个接口看到DeviceViewModel什么不可避免地需要第二个选项。

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

我们现在有两种选择的组合。

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

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

+0

我得到的第一个选择,但我无法绕过第二个选择。你能好好谈谈那一点吗? – faldeland

+0

@faldeland我更新了我的答案 –

+0

此信息非常有帮助。我希望尽可能遵循最佳做法。我正在寻找一种可靠的方式来通过MainViewModel进行导航。我相信我会像你一样深入到底。我希望我能找到一个有这些实践的开源项目。 – faldeland