C# 正确的MVVM视图模型和模型模式

C# 正确的MVVM视图模型和模型模式,c#,wpf,mvvm,C#,Wpf,Mvvm,我还没有找到确切的答案。有些人提到直接绑定到模型不适合MVVM,但是我试图确定以下模式是否仍然遵循MVVM: 视图: 视图模型: private ProcessingTaskModel _infoForProcessing; public ProcessingTaskModel InfoForProcessing { get { return _infoForProcessing; } private set { _in

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

视图:


视图模型:

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)

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

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


我还确保尽可能多地封装,只公开视图和ViewModel需要查看的属性,同时限制setter。

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

一个常见的想法是,出于某种原因,您无法直接绑定到视图中的模型属性

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

{Binding ViewModel.Model.Property}

这也意味着您没有一直将属性从模型复制到ViewModel。

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

  • 具有独立的视图模型和模型对象。在这个场景中,每个都有自己的方法。INPC用于查看模型类和模型类中的数据库方法。(如图所示)

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

  • 我通常在自己的项目中这样做,因为它提供了更好的关注点分离,并限制了代码/数据复制


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

    最好将其列为项目符号

  • 模型DTO可以遵守INotifyPropertyChange并成为绑定目标
  • VM应该处理从视图启动的任何数据库调用,并填充VM上存储的数据
  • 我更喜欢将我的
    模型
    保留为POCO类型的实体,而获取模型的操作

    您所描述的
    模型
    实际上是数据库操作的属性;它的地位


    简短回答
    模型上的所有项目都应该在VM上移动和完成,并相应地绑定。

    我认为任何一种方法都可以。MVVM是一种模式,而不是硬规则。我会以一种对您有意义的方式来实现它。有些人提到直接绑定到模型不适合MVVM。有些人并不聪明。MVVM中没有任何东西要求模型是纯POCO,没有任何逻辑。在我看来,业务逻辑实际上属于模型内部。我是说浮动在层之间的DTO不应该有模型(业务)逻辑。@BradleyDotNET所以你会使用像ResolveBatchInfo(…)这样的函数,并将这些操作重构到它们自己的类中进行进一步的抽象?或者,您是否建议应重命名ProcessingTaskModel类,以反映它是什么->ProcessingTaskViewModel,因为它实现了INPC,并在不实现INPC的情况下保留数据库逻辑“Model”?然后让主视图模型在ProcessingTaskViewModel和新模型之间协调数据。@phillk6751我说这两种方法都是有效的。我通常的方法是第一种,因为它提供了更好的关注点分离和更少的数据/代码复制。我将此添加到我的答案中。@phillk6751这将是我列出的第一种方法(您列出的第二种)。在我通常的方法中,有一个“数据”层实现INPC,但没有其他逻辑。然后,视图模型根据视图的需要公开数据层,并且模型与数据层交互以实现业务逻辑、持久性等。换句话说,模型是图像中模型和控制器块的组合。您关于不将属性从模型复制到视图模型的观点是我的主要观点之一。在这种情况下,我有多个ViewModel,它们可能会重用由另一个ViewModel绑定的一些数据,并且无法直接访问其他ViewModel的属性。我可以想象,如果由于某种原因模型中的数据发生了更改,如果不直接绑定到模型属性,您可能会留下不干净的视图数据。
    {Binding ViewModel.Model.Property}