【问题标题】:Proper MVVM ViewModel and Model pattern正确的 MVVM ViewModel 和模型模式
【发布时间】:2015-08-24 14:11:50
【问题描述】:

我还没有找到确切的答案。有些人提到直接绑定到模型不适合 MVVM,但是我正在尝试确定以下模式是否仍然遵循 MVVM:

查看:

<TextBox Text="{Binding InfoForProcessing.BatchId}"/> <TextBox Text="{Binding InfoForProcessing.BatchStatus}"/>

视图模型:

private ProcessingTaskModel _infoForProcessing;
public ProcessingTaskModel InfoForProcessing
{
    get
    {
        return _infoForProcessing;
    }
    private set
    {
        _infoForProcessing = value;
        RaisePropertyChanged();
    }
}
....
//doing some processing...then tell Model to populate the data:
InfoForProcessing.ResolveBatchInfo(...);

模型:(实现 INotifyPropertyChanged)

private string _batchId;
public string BatchId   //VIEWABLE
{
    get
    {
        return _batchId;
    }
    private set
    {
        _batchId = value;
        RaisePropertyChanged();
    }
}

private string _batchStatus;
public string BatchStatus  //VIEWABLE
{
    get
    {
        return _batchStatus;
    }
    private set
    {
        _batchStatus = value;
        RaisePropertyChanged();
    }
}

public bool ResolveBatchInfo(...){
    //Get data from Database...
    ...
    //Now Populate Properties with retrieved data (or return false on error)
    BatchId = dr[0].ToString();
    BatchStatus = dr[1].ToString();
    return true;
}

我看到了另一种方法。我可以将这些属性复制到 ViewModel,绑定到它们,并在 Model 返回时让 ViewModel 填充它们。

对于我这里的当前项目,模型中的一些数据是稍后将执行的查询的依赖项

我也确保尽可能地封装,只公开 View 和 ViewModel 需要看到的属性,同时限制 setter。

【问题讨论】:

  • 我认为任何一种方式都可以。 MVVM 是一种模式,而不是硬性规则。我会以对您有意义的方式实现它。
  • 有人提到直接绑定模型不适合MVVM有些人不聪明。

标签: c# wpf mvvm


【解决方案1】:

一种常见的思路是 - 由于某种原因 - 您不能直接绑定到视图中的模型属性。

但是,鉴于 MVVM 的目标是将 UI/View 从逻辑中抽象出来,这种形式的绑定不会破坏这一点:

{Binding ViewModel.Model.Property}

这也意味着您不会一直将属性从模型复制到视图模型。

【讨论】:

  • 您关于不将属性从模型复制到视图模型的观点是我的主要观点之一。在这种情况下,我有多个 ViewModel,它们可能会重复使用由另一个 ViewModel 绑定的某些数据,并且无法直接访问其他 ViewModel 的属性。我想如果由于某种原因模型中的数据发生变化,如果没有直接绑定到模型属性,您可能会留下不干净的视图数据。
【解决方案2】:

在我看来,您的设计不符合标准,因为您的数据对象包含模型逻辑(ResolveBatchInfo 方法)。以下是两种可能的解决方案:

  1. 具有单独的视图模型和模型对象。在这种情况下,每个人都有自己的方法。 INPC 用于 View Model 类和 Model 类中的数据库方法。 (如图here

  2. 让您的 POCO 在层之间“浮动”。这里重要的部分是除了INPC之外,对象中没有逻辑,它们只是数据。在这种设计下,您将拥有一个单独的模型类来封装数据操作,并拥有一个返回填充的BatchInfo 对象的方法。

我通常在自己的项目中执行 (2),因为它可以更好地分离关注点并限制代码/数据复制。

当然,对于这三种方法中的任何一种(我的两种加上你的),最重要的因素是编写有意义的代码,而不是“纯”MVVM。因此,请选择能让您的生活变得最轻松的设计。

【讨论】:

  • MVVM 中没有什么要求模型是纯 POCO,没有任何逻辑。在我看来,业务逻辑实际上属于模型内部。
  • @poke 我同意。我是说在层之间浮动的 DTO 不应该有模型(业务)逻辑。
  • @BradleyDotNET 所以你会采用像 ResolveBatchInfo(...) 这样的函数并将这些操作重构到它们自己的类中以进一步抽象吗?或者您是否建议应该重命名 ProcessingTaskModel 类以反映它是什么 -> ProcessingTaskViewModel 因为它实现了 INPC,并在不实现 INPC 的情况下保持数据库逻辑“模型”?然后让主 ViewModels 调解 ProcessingTaskViewModel 和新模型之间的数据。
  • @phillk6751 我是说这两种方法都是有效的。我常用的方法是第一种,因为它提供了更好的关注点分离和更少的数据/代码复制。我将此添加到我的答案中。
  • @phillk6751 这将是我列出的第一种方法(您列出的第二种方法)。在我通常的方法中,有一个“数据”层实现了 INPC,但没有其他逻辑。然后视图模型根据需要为视图暴露 Data 层,模型与 Data 层交互用于业务逻辑、持久化等。换句话说,模型是你的图像中的模型和控制器块的组合。
【解决方案3】:

我个人不介意任何一种方式,但很多人(包括我目前工作的公司)认为将模型的属性包装在视图模型中是一种更“纯粹”的方法。不过就我个人而言,我认为将 MVVM 视为良好实践的指南很重要,而不是一套绝对要遵循的规则。我曾经遇到过一些实例,有人告诉我忘记包装模型的属性,仅仅是因为它需要快速完成。

【讨论】:

    【解决方案4】:

    最好将其列为项目符号

    1. 模型 DTO 可以遵守 INotifyPropertyChange 并成为绑定目标。
    2. VM 应处理从 View 发起的任何数据库调用,并填充 VM 上存储的数据。

    我更喜欢将我的Models 保留为 POCO 类型的实体,而不是 获取模型的操作

    您所描述的Model 实际上是数据库操作的属性/属性;它的状态。


    简答

    您的模型上的所有这些项目都应该在您的 VM 上移动和完成并相应地绑定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-06
      • 1970-01-01
      • 2013-12-09
      • 2016-07-17
      • 2014-05-27
      • 2023-03-17
      • 1970-01-01
      • 2011-08-14
      相关资源
      最近更新 更多