【问题标题】:MVVM - Should the View have a reference to the Presenter/ViewModel?MVVM - View 是否应该引用 Presenter/ViewModel?
【发布时间】:2009-09-16 08:47:41
【问题描述】:

我一直在查看 PRISM 2 示例,以了解如何最好地处理我正在开发的新应用程序,这将是一个 PRISM 2/WPF 应用程序。特别看一下 PRISM 附带的 View Injection 示例应用程序,我注意到所有视图都实现了一个接口,该接口允许演示者(或 ViewModel)与视图交互。

过去我是用相反的方式做的,我将presenter注入到视图中,这样视图就可以直接调用presenter上的方法,有点像这样:

    public partial class SomeView : ModuleBase
    {

        private ISomePresenter _somePresenter;

        public SomeView (ISomePresenter somePresenter):this()
        {
            // Give the view a reference to the presenter
            _somePresenter = somePresenter;
            // Bind the View to the presenter
            DataContext = _somePresenter;
        }

    private void btnSubmit_Click(object sender, RoutedEventArgs e)
    {
        // The view can call actions directly on the presenter (OK I should probably use a command for this)
        _somePresenter.SomeAction();
    }
}

上面的技术对我来说似乎足够合理,但看看样本我开始质疑这种方法。是否有人对解决此问题的最佳方式有看法(没有双关语)?

  • 将演示者添加到视图并让视图与演示者交互
  • 将视图添加到演示者并让演示者与视图交互
  • 我还没有想到的完全不同的东西?

【问题讨论】:

    标签: mvvm prism mvp


    【解决方案1】:

    在 MVVM 中将 ViewModel 映射到 View 的最常见方法是使用 DataTemplate

    <DataTemplate DataType="{x:Type vm:SomeViewModel}">
        <v:SomeView />
    </DataTemplate>
    

    当您在 ContentControl 或 ItemsControl 中显示 ViewModel 实例时,WPF 将自动为 ViewModel 实例化适当的 View,并将 View 的 DataContext 设置为 ViewModel 实例。

    那样,您在 ViewModel 中没有任何对 View 的引用,而 View 仅通过 DataContext 属性引用 ViewModel。如果您确实需要在 View 的代码隐藏中访问 ViewModel,您可以随时转换 DataContext(但这意味着 View 知道 ViewModel 的实际类型,这会导致耦合)

    【讨论】:

    • 我最近在想这个。我几乎只使用 DataTemplates,我开始觉得 DataTemplate 就是视图。这意味着指定 DataType 参数会将视图耦合到视图模型。我对这种类型的耦合没有意见,但它违背了 Prism4 文档中的一句话:“同样,理想情况下,视图不应依赖于视图模型的任何特定实现。”对我来说,视图是扔掉的部分,随时可能被另一个视图取代。因此,将其耦合到视图模型是可以接受的。
    【解决方案2】:

    我认为这完全是品味问题。就个人而言,我喜欢您在您正在查看的样本中看到它的方式。 IView 有一种方法,即 SetViewModel(...)。 IViewModel 有一个 Object 类型的 View 属性,它本质上返回 DI 实例化的 IView。

    我喜欢这种方式的原因是我几乎总是想先创建一个 ViewModel,并且我希望代码中的 nobody 能够对我的 IView 做任何事情,除了获取对实例的引用(用于视图注入或绑定视图以说一个 ContentControl),这就是它的类型对象的原因。如果任何代码需要与视图对话,对我来说,它总是通过虚拟机......即使这样,视图通常也会通过绑定来更新。从 View->ViewModel->UpdateBinding->View 去感觉会比 VM->UpdateBinding->View 更奇怪

    要回答这个问题,我通常不需要在代码隐藏中引用演示者。通常我可以使用绑定到 VM 的视图中的命令来处理它。 在某些情况下,您可能希望保留对演示者的引用来执行示例中的操作,但如果使用正确的工具集,这是可以避免的(使 SL 更难,因为它没有内置命令)。

    就像我说的,这完全取决于口味......

    -杰尔

    【讨论】:

      猜你喜欢
      • 2011-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多