Mvvm 我应该在容器中注册ViewModels吗?

Mvvm 我应该在容器中注册ViewModels吗?,mvvm,dependency-injection,autofac,caliburn,Mvvm,Dependency Injection,Autofac,Caliburn,我应该在容器中注册ViewModels并从中解析吗 好处: 激活视图模型时,我可以执行一些操作 容器将为我注入依赖项 缺点: ViewModel生命周期管理可能很棘手: 如果将ViewModel设置为singleton,则无法实例化同一类型的多个控件 如果我将ViewModel设置为瞬态,那么当我实际期望注入同一个实例时,我很容易就会遇到具有多个不同实例的情况 正确答案是什么? 如果我能减轻终身缺点,我宁愿注册 如果有必要,我会使用Caliburn和Autofac。2)的好处足以让容器处

我应该在容器中注册ViewModels并从中解析吗

好处:

  • 激活视图模型时,我可以执行一些操作
  • 容器将为我注入依赖项
  • 缺点:

  • ViewModel生命周期管理可能很棘手:
    • 如果将ViewModel设置为singleton,则无法实例化同一类型的多个控件
    • 如果我将ViewModel设置为瞬态,那么当我实际期望注入同一个实例时,我很容易就会遇到具有多个不同实例的情况
  • 正确答案是什么? 如果我能减轻终身缺点,我宁愿注册

    如果有必要,我会使用Caliburn和Autofac。

    2)的好处足以让容器处理viewmodels。我们使用自己的MVVM框架,其中视图实例和视图模型实例之间存在严格的一对一关系。因此,缺点是不存在的

    在需要在视图之间共享数据的情况下,我们通过将共享服务实例注入viewmodels来实现这一点


    除此之外,还有其他情况下您希望在多个视图之间共享一个viewmodel实例吗?

    不确定autofac或Caliburn(可能仍然适用),但当它进入Unity容器时,我将仅在以下情况下注册viewmodel

    当容器被处理掉的时候,我需要把它处理掉。您可以创建一个生命周期管理器来存储新创建的(非单例)视图模型实例

    container.RegisterType<MyViewModel>(new DisposeableInstanceLifetimeManager());
    ...
    container.Resolve<MyViewModel>();  // here all dependencies will get injected
    ...
    container.Dispose(); 
    
    container.RegisterType(新的DisposableInstanceLifeTimeManager());
    ...
    container.Resolve();//这里将注入所有依赖项
    ...
    container.Dispose();
    
    如果您想共享数据,我倾向于创建一个子(子)容器,并将模型注册为单例,让多个视图模型共享同一个模型

    var child = container.CreateChildContainer();
    child.RegisterInstance(model, new ContainerControlledLifetimeManager());
    child.Resolve<MyViewModel1>();
    child.Resolve<MyViewModel2>(); // both can share the model instance
    
    var child=container.CreateChildContainer();
    RegisterInstance(model,newcontainerControlledLifetimeManager());
    child.Resolve();
    child.Resolve();//两者都可以共享模型实例
    
    (注意:使用Unity时,在ViewModel上使用
    Resolve
    时,即使未向容器注册,也会注入所有依赖项)


    否则,除非您需要一个单例ViewModel(尽管我想不出什么时候它会有用),否则我觉得将ViewModel添加到容器中只会添加更多代码,没有任何好处。

    容器是一个由它创建的对象所占据的生态系统。视图模型与这些居民交互,因此也是生态系统的一部分。为了准确反映这种关系,您应该在容器中注册视图模型

    您应该始终对视图模型使用
    InstancePerDependency
    。视图模型表示特定UI的状态和行为-它是控件的非特定框架的类似物。正如通常不能将同一控件实例放在UI树中的两个位置一样,也不能重用同一视图模型实例


    如果可以,我们将其称为
    ViewsModel
    :-)

    当一个ViewModel需要注入到其他几个视图模型中时,情况如何?最简单的例子-状态栏。假设窗口上有几个控件(由多个视图模型支持),并且它们中的每一个都会在状态栏中不断更新消息。关于使用VIEWMDEST同时返回多个控件,请考虑网格,当您选择要查看详细信息的行时。当前行和详细信息控件很可能绑定到同一视图模型,只是显示方式不同而已。不过我喜欢你的第一段@Konstantin Spirin:对于状态栏,您将拥有一个实现视图模型之间通信的共享服务,而不是直接共享视图模型(@Peter Lillevold也建议了这一点)。对于网格/行示例,我几乎总是为行创建一个视图模型,为“详细信息”对话框创建一个单独的视图模型。它们可能都使用相同的实体实例,但具有不同的配置文件和意图,例如行上的编辑命令和对话框上的保存/取消命令。@Konstantin Spirin:我刚刚意识到您建议将
    StatusBarViewModel
    注入
    StatusBarService
    。我的建议正好相反:
    IStatusContext
    将是两个视图模型之间的通信点,但它并不引用视图模型本身。因此,
    StatusBarViewModel
    只需要解决一次,避免了这些问题。每个选项卡都包含报表,所有报表都应使用相同的日期选择器。你将如何实现这一要求?@康斯坦丁-我会考虑这样的观点作为几个视图(与相应的VIEW模型)。一个视图/模型表示处理选定日期的整个窗口,然后每个选项卡一个视图/模型。使用数据绑定,您可以轻松地将主视图中的SelectedDate绑定到每个子视图上的属性。应用程序的主窗口是singleton的最佳候选对象。主窗口通常包含在整个应用程序中共享的元素。例如,状态栏。使用Unity时,我做了非常类似的事情,但很容易迷失方向,因为您需要考虑注册哪个ViewModel,不注册哪个ViewModel。另外,将ViewModel作为依赖项是非常可怕的,因为Unity可以创建新实例,即使您还没有注册它。