在哪里将 entities/models 转换为 MVVM 中的视图模型?

Where to convert entities/models to viewmodels in MVVM?

在 MVC 中它非常简单:

客户端发出请求,控制器要求业务逻辑做一些花哨的事情,业务逻辑要求存储库 return 一些数据,然后存储库 return 的数据和业务逻辑负责转换数据从实体到视图模型,returned 到客户端。

在 MVVM 中,我几乎迷路了,因为视图模型本身负责向业务逻辑发出请求,所以没有像控制器那样的 "middle layer"。我可以在商业逻辑项目中实现映射器,但由于视图模型负责向商业逻辑询问数据,它会创建循环引用。

那么我必须在哪里实现这个 "magic" 呢?

根据 mvvm-light 参考,我假设这里有一个 WPF 应用程序。 我在第 1 段中提到了您的业务逻辑(我将从这里将其称为服务)负责转换为视图模型。我会说该服务应该不知道该视图。所以在那种情况下,控制器(或控制器或模型绑定器调用的映射器)将处理映射。

在 MVVM 中(我在此处尝试为您进行比较时的意见)ViewModel 的行为很像控制器,因为它会获取模型、映射并绑定到可观察对象。然后也是绑定view的model(mvc中经常用到的view model)

所以我认为这里的诀窍是移动映射应该出现的位置。服务不应该对视图有任何了解。他们没有与视图耦合,这是一件好事。

在 MVVM 中,您所指的 "business layer" 是 "model" - 实际上,视图模型之后的任何内容都被视为 "model" 的一部分。然而,在我做过的任何工作中,我总是将此模型拆分为 n 层 ,通常使用控制器样式 class,使用服务从中检索数据实体一个数据存储库。

Where to convert entities/models to viewmodels?

严格来说,你没有。视图模型可以 包含 实体(即 VM 具有它们的 ObservableCollection),或者视图模型可以 wrap 实体(在列表控件中很有用,其中您可能需要在每行的基础上显示选项或执行操作)。

实体的 MVC 方法比 MVVM 有点脏,您最终会得到一个更丰富的业务模型,而不是一个很好的精益实体。在 MVVM 中,"richness" 主要由视图模型拆分和处理,并且您尝试使数据实体尽可能简单(是的,您可以在实体中包含诸如验证之类的内容,但您应该只在必要时才这样做,其他时候应该在 VM 或模型中的某个地方处理验证。

你的问题问错了。视图模型代表用户与您的应用程序交互背后的逻辑,所以问题真的应该是 "how does the view model acquire entities and models when user interaction requests them?"。答案是:"With a dependency injection framework, e.g. Ninject"。这允许您将实体范围限定为 WPF 应用程序中的页面、MVC 或 WCF 应用程序中的 Web 请求、任何外部控制台实用程序中的单例或测试框架中的模拟对象……所有这些都无需您的视图模型了解或关心关于这些实体或提供它们的服务是如何在内部创建或工作的。

我将尝试通过一个简单的示例提供一些背景信息。

请注意,下面的所有代码都只是概念性的,并且是在此处而不是在 VS 中编写的。

将您的 ViewModel 视为模型的包装器。 您的模型由 属性 公开,因此您可以从视图绑定到它或绑定到它的属性。

您的视图模型:

  public class SomeEntityViewModel : NotificationObject
  {
       private SomeEntity _someEntity;
       public  SomeEntity SomeEntity
       {
           get{ return _someEntity;}
           set
           {
               _someEntity = value;
               RaisePropertyChanged("SomeEntity");
           }  
       }  
  } 

现在假设您向服务器发送请求并等待响应。

我们还假设您有一个更高级别的对象(如父 ViewModel)来启动您的 VM:

  public class SomeEntityContainerViewModel : NotificationObject
  {
      public ObservableCollection<SomeEntityViewModel> Items;

      public void async OnRequestNewEntity() 
      {
         SomeEntity newEntity = await _someEntityService.CreateSomeEntityAsync();
         var vm = new SomeEntityViewModel{ SomeEntity = newEntity};
         Items.add(vm);
      }
  }

你的 SomeEntityContainerView 其中 SomeEntityContainerViewModel 是 DataContext :

  <UserControl>
      <Button Command="{Binding RequestNewEntityCommand}" />
      <ItemsControl ItemsSource="{Binding Items}" />
  </UserControl>

你的 SomeEntityView 其中 SomeEntityViewModel 是 DataContext :

    <UserControl>
        <TextBlock Text="{Binding SomeEntity.Name}" />
    </UserControl>

最简单的设计:

您的模型需要 "dumb",只有数据。 您的 ViewModel 最接近于 Controller,它将处理逻辑,并且它是将 包装(而不是转换) 您的模型在视图模型中的组件。

在上面的例子中,我们有一些更高的对象,一个父 ViewModel,它启动了我们的 ViewModel。

这相当于控制器的作用域,在 DOM 中其下还有其他嵌套的控制器。