【问题标题】:Why implement an interface on viewmodel and view in mvvm为什么要在 viewmodel 上实现接口并在 mvvm 中查看
【发布时间】:2012-07-12 21:20:18
【问题描述】:

我对 MVVM 模式很陌生,所以请多多包涵。我在 wpf +mvvm + prism 中看到了实现,其中所有视图都倾向于将 IView 作为最顶层的界面。然后各个模块中的视图有一个视图特定的接口,如 IViewA、IViewB 等,它们实现了 IView 接口。甚至 viewmodel 也有 IViewModel 最顶层的接口,并且后续模块有 IViewAViewModel 、 IViewBViewModel 等继承自 IViewmodel。 IViewmodel 引用了 Iview,而 Iview 引用了 IViewModel。

namespace xxx.xxx.infrastructure
{
public interface IView
{
  IViewModel ViewModel {get;set;}
}

public interface IViewModel 
{
  IView View {get;set;}
}

public abstract class ViewModelBase : IViewModel, INotifyPropertyChanged
{

   public IView View {get;set;}

   public ViewModelBase(IView view)
   {
     View = view;
     View.ViewModel = this;
   }
   //INotifyPropertyChanged left out
 }
}

namespace xxx.xxx.Modules.Customer
{
   public interface ICustomerDetailsView : IView
   {

   }

   public partial Class CustomerDetailsView : UserControl, ICustomerDetailsView 
   {
       public CustomerDetailsView ()
       {
         InitializeComponent();
       }

       //Is this implementation acceptable?The view is supposed to have zero code in       the code behind.....
        public IViewModel ViewModel
        {
          get
          {
            return (ICustomerDetailsViewViewModel)DataContext; 
          }
          set
          {
             DataContext = value;
          }
        }

    }  

    public interface ICustomerDetailsViewViewModel : IViewModel
    {
       string Message {get;set;}
    }

     public class CustomerDetailsViewViewModel : ViewModelBase,       ICustomerDetailsViewViewModel 
    {
      //Will be injected by unity as i have set up mappings in module initilize.
      public CustomerDetailsViewViewModel(ICustomerDetailsView view)
          :base(view)
      {
      }

       public string Message
       {
          //INotifyPropertyChanged left out for brevity
          get;set;
       }
   }

我有几个问题。

1.)这种违反 MVVM 的行为是不是因为文件后面的代码应该是零代码?

2.)在 MVVM 视图模型中不应该担心视图或其合同?上面的实现不会破坏它吗?

3.)我不明白这个实现有什么用。事实上,这接近 MVP 并且需要大量代码。

4.)如果这是一种可接受的实现方式,我是否需要为所有模块中的所有视图和视图模型提供接口?

【问题讨论】:

  • 我与 WPF 的合作不多,但我同意您作为设计实践的观点。 VM 不应该引用视图,我认为不需要它,除非您没有正确使用双向绑定。关于无处不在的接口......这是静态语言的不幸事实,其中合约需要采用接口的形式。 Unity 应该为它的 DI 东西提供苛刻的接口..
  • @Hasith 其实并不是视图的具体实现,只是视图的一个接口。我可以说这仍然满足 MVVM,因为 VM 不知道实现 IView 的窗口/页面
  • 是的,但是视图模型仍然需要了解视图的契约。这意味着比与独立 ViewModel 更多的耦合。为什么在双向绑定到位时需要它?想象一下,当您需要多个视图来共享同一个视图模型时(例如,在同一个窗口中紧密相关的多个 UI 组件)。不知道它在 WPF 中是如何工作的,但我已将其用作 Javascript MVVM 框架中的强大实践。
  • “视图模型”不是模型;它更像是一个“控制器”或“演示者”,将视图与真实模型分离。当然,真实模型是可选的,在许多情况下,VM 充当模型......
  • @Hasith:完全同意你的观点,不需要在 ViewModel 中注入任何 IView。 MVVM 基于 Presentation Model 模式,所以 View 担心与 View(Presentation)Model 同步状态。 ViewModel 只需要引发它状态已更改的事件,并且 View 将同步(通过事件订阅或绑定)。如果 IView 注入 ViewModel,则意味着 ViewModel 担心与它 View 同步状态,看起来像 MVP Supervising Controller。

标签: wpf silverlight mvvm prism


【解决方案1】:

首先来自 Rachel 关于视图模型的非常好的评论:

请记住,使用 MVVM,您的 ViewModel 就是您的应用程序。视图是 只是一个漂亮的界面,允许用户与您的交互 视图模型。

1) IView 对我来说违反了 MVVM,但代码隐藏当然可以用于 ui 的东西。 viewmodel 应该没有对视图的引用。请参阅 Hasith 的第一条评论

2) 查看我的块引用

3) 我和你在一起 - 我从不在我的项目中使用类似的东西

4) 请用简单的方法做 MVVM - 没有耦合,使用 di、ioc、命令、行为,对我来说最重要的是:首先是 viewmodel:)

【讨论】:

  • 正确。 ViewModel 是愚蠢的容器,不知道查看它们的内容。 我强烈建议将控制器引入 MVVM 以确保不需要这种情况。 @Peter Ritchie:VM 不应该成为控制器……这是传播 MVVM 示例方式的一个根本缺陷。在 MVCVM 上滚动! :)
【解决方案2】:

基本上,我们只需要用于注入的接口。有两种方式:

  • 向视图注入 ViewModel

这意味着 ViewModel 不再有任何对 View 的反向引用。这意味着在对 ViewModel 进行单元测试时,您不需要模拟视图。此外,它使代码更清晰,因为在 View 的构造函数中,它只是将 DataContext 设置为注入的 ViewModel。

  • 向 ViewModel 注入视图。

它避免将工作流逻辑保留在表示层中。这意味着应用程序层继续负责应用程序的工作流程。 这样,工作流逻辑与视图高度耦合,因此很难为此编写单元测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-12
    • 2011-05-05
    • 2010-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多