【问题标题】:MVVM WPF ViewModels for Adding New Entity用于添加新实体的 MVVM WPF ViewModel
【发布时间】:2010-11-10 08:11:59
【问题描述】:

我对 WPF 中的 MVVM 的概念是,我们为您的应用程序中的每个模型都有一个 ViewModel。这意味着如果我们有 Customer 类(实体),那么我们将有 CustomerViewModel。 CustomerViewModel 将具有代表客户所需的所有属性。 CustomerView 用户控件将负责为 Customer 模型创建 UI。

现在,假设我们要添加一个新客户。因此,我们有一个由 FirstName、LastName 等组成的表单。我们是否需要一个 ViewModel 来处理这种情况。我的意思是我所要做的就是从 TextBox 中获取所有输入值并创建一个 Customer 对象,然后将其保存到数据库中。我为什么要为这种情况创建一个 ViewModel 呢?

【问题讨论】:

    标签: wpf mvvm


    【解决方案1】:

    您不需要单独的 ViewModel 来添加,您只需要一个 ViewModel 来执行编辑和添加场景。如果您可以从编辑页面中删除记录,那么 ViewModel 也应该能够删除。无论数据如何,您的 ViewModel 都应该反映您的 View 公开的功能。

    我认为您应该重新考虑为每个模型设置一个 ViewModel。我喜欢将 ViewModels 视为对插入数据的行为进行规范化。通过为每个模型类设置一个 ViewModel,您迟早会遇到架构问题。我从自上而下的概述中查看应用程序,我的 UI 试图完成什么,从那里我将到达 ViewModel,最终我将到达我的 DataFactory,ViewModel 如何映射到数据几乎总是不是 1 比 1,除了对于最简单的视图。如果您尝试将 1 映射到 1,您的 UI 会很糟糕,或者您的数据不会被很好地标准化。

    我们这里的堆栈是:

    1. 查看
    2. ViewModel(控制用户可以在视图中执行的所有操作,包装我们 POCO 的属性)
    3. DataFactory(将我们的 POCO 映射到实体框架对象和 CRUD)
    4. POCO(业务逻辑,所有规则和验证)
    5. 实体框架(模型、数据访问)

    这里需要注意的是,ViewModel 包含来自多个 POCO 的属性!

    我们通过 StructureMap 注入 DataFactory,并使用 xUnit 和 Moq 进行单元测试。

    为了回答您的第二个问题,我将创建一个单独的仅视图以作为用户控件放入。但是您的应用中仍然应该有一个 CRUD ViewModel,它以用户友好的方式封装所有这些功能。

    谢谢。

    【讨论】:

    • 您能否强调一下您的“NO”回答!我的哪个问题你回答“否”作为答案。
    • 通过使用像“CustomerViewModel”和“CustomerView”(UserControl)这样的单个 ViewModel,我可以在需要查看客户时简单地放入 CustomerView。
    【解决方案2】:

    让我们暂时假设没有商业模式。你所拥有的唯一就是一个视图。如果您只是为该视图建模,而不知道数据在系统其他地方的含义,那就是 ViewModel。

    ViewModel 的目标是对它所支持的视图进行建模。这与在您的业务领域中为客户的想法建模不同的目标。如果说每个业务实体有一个 ViewModel,那么就是说每个业务实体有一个视图,这会导致以数据为中心的普通 UI。

    在您的特定情况下,请考虑客户编辑视图。它具有与客户属性相对应的字段,因此似乎很适合直接绑定到客户。但是,在客户对象的什么地方建模了“提交”操作? “取消”动作在哪里建模?字段 X 是从列表中选择的枚举值在哪里建模?

    密码呢?如果作为二进制哈希值保存,视图是否知道如何对其文本进行哈希处理?如果系统有密码强度要求怎么办?

    ViewModel 是业务模型和 UI 之间的砂浆。它从一个人那里得到关注,并将它们转化为另一个人的术语。这是解决上述所有问题的地方。说 ViewModel 没有必要就是忽略它的必要性。

    【讨论】:

      【解决方案3】:

      首先,这不是 MVVM 的主要目的,“镜像”一切。视图应该提供用户输入的方法,当然不会处理对任何数据库层的调用。 ViewModel 应该是一个与 GUI 无关的应用程序主干,它肯定应该处理客户的创建。

      也就是说,您应该做的是拥有一个 ViewModel,它代表一个用于处理客户的工作区,而不仅仅是一个客户 ViewModel。如果您真的想保存一些正在创建的对象,请向该工作区添加创建和添加新客户(而不是 CustomerViewModel)的可能性。这样,您可以拥有一个工作区视图,其中包含客户的每个相关/必需属性的元素,并通过调用添加到该工作区 ViewModel 的一些命令,您可以获得填充这些的当前值(绑定到 ViewModel 的数据)直接向客户模型查看元素。

      考虑一下,如果你稍微重构一下,你是否可能会放弃特定的客户(和其他模型)ViewModel,最好避免在没有明确原因的情况下盲目地遵循某种模式。

      【讨论】:

      • 那么,您将如何表示用于添加客户的 ViewModel? ViewModel 的用途是什么,因为稍后它将把值传输到业务类,Service/Repository 将使用该业务类将其保存到数据库中。
      • 想象一下您的应用程序中有一个“AddCustomer”选项卡。该选项卡可以包含名称、地址、帐号等的文本框字段。然后,例如,您可以有一个 AddCustomerViewModel,它有一个“SendToRepository”命令。拥有这个中间 VM 的一些原因是 1) 图形界面与应用程序逻辑的分离 - 使应用程序逻辑的简单可测试性成为可能,以及轻松更改 UI 层的可能性。 2) ViewModel 常用于适配 UI 和业务层之间的数据,简化代码(例如需要更少的转换器)等
      • continue: 3) View 和 ViewModel 之间的数据绑定通常会产生更简洁的代码,最重要的是,如果应用程序逻辑更改 ViewModel 并且不会尝试直接操作 View 及其资源,这些代码会表现得更好
      【解决方案4】:

      这种虚拟机抽象的一个原因是可测试性。您需要 ViewModel 的另一个原因是因为它基本上是一个数据传输对象,它可能是单个容器中多个模型的字段的组合,与您当前的视图更相关。拥有 VM 的另一个原因是利用 WPF 的两种方式绑定功能。

      使用您的常规模型(普通 POCO),您可以在模型更改时更新视图,但是由于您的模型没有实现依赖属性(很可能),您将无法利用更新模型的优势WPF 控件中的值发生变化。这意味着您必须手动添加一个处理程序并将此值从该控件复制回模型之类的东西。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-13
        • 2020-08-26
        • 2013-01-16
        • 1970-01-01
        相关资源
        最近更新 更多