【问题标题】:Should ViewModel have pass-through DependencyProperties that bind to DependencyProperties on the Model?ViewModel 是否应该具有绑定到模型上的 DependencyProperties 的传递 DependencyProperties?
【发布时间】:2012-11-26 21:47:16
【问题描述】:

我是 WPF/MVVM 的新手,我发现的示例似乎并未涵盖我面临的问题。

我有一个用于管理相当复杂的业务配置对象的屏幕。在 MVVM 中,我认为这意味着我应该拥有以下内容:

  1. 逻辑接近于零的 XAML 视图
  2. 具有屏幕逻辑的 ViewModel 类
  3. 我平时的业务类填补了 Model 的角色,拥有了所有的业务逻辑

在我的情况下,有一些业务规则说更改我的业务类的 fieldA 可能会产生各种副作用,例如更改 fieldB 的值,或填充整个子对象列表。

我可能是错的,但我认为我应该将这些规则封装在业务类中,因为这些规则实际上与其说是关于屏幕,不如说是关于实体。

当然,这些副作用需要立即回到屏幕上。

所以从用户的角度来看,他可能会编辑 fieldA,并在 View 上看到 fieldB 更新。

我了解如何将数据从 View 绑定到 ViewModel。

但就我而言,我似乎需要两层数据绑定:一层在 View 和 ViewModel 之间,另一层在 ViewModel 和 Model 之间。

鉴于我两次遇到基本相同的问题,我认为应该采用一种解决方案。所以我把我的 Model 类变成了一个 DependencyObject,我把它的属性变成了 DependencyProperties。

以 fieldA 为例,它会出现在所有三层中:

  1. 作为数据绑定到 ViewModel.FieldA 的可视化组件查看,例如 text="{Binding FieldA, Mode=TwoWay}"
  2. ViewModel 作为 DependencyProperty “向上”绑定到视图,“向下”绑定到模型
  3. 作为 DependencyProperty 的模型

我不希望通过跳过第 2 部分来直接将我的 View XAML 耦合到业务对象,这对我来说似乎不是一个干净的模式应用程序。或许这是误入歧途。

我的 ViewModel 中似乎需要一个“传递 DependencyProperty”。

我的问题:

  • 这是正确的通用方法还是我认为这一切都错了?
  • 是否有使用这种传递方法的示例?
  • 谁能给出一个代码示例,说明在 ViewModel 和 Model FieldA DependencyProperties 之间创建传递绑定的正确方法?

【问题讨论】:

    标签: c# wpf mvvm


    【解决方案1】:

    我自己也在为这个问题苦苦挣扎,我想在 MVVM 方面这是一个非常常见的问题。我的回答是避免使用DependencyObjectINotifyPropertyChanged 污染域,因为它在某种程度上否定了使用 ViewModel 的有效性。

    ViewModel 的目标是以与特定视图相关的方式公开模型。当虚拟机本质上需要公开整个域对象时,它会变得混乱。我将这些称为“编辑器”视图模型。这些是从域对象传递属性的最诱人的方法。在这些情况下,我为 VM 提供对域对象(组合)的引用并通过 getter 和 setter。如果 UI 需要刷新或显示验证错误,ViewModel 采用 INotifyPropertyChangedIDataErrorInfo 而不是 DependencyProperty 向 UI 发出信号。如果域引发验证错误,则 VM 会捕获它并将其准备到视图的数据错误信息详细信息中。

    【讨论】:

      【解决方案2】:

      我同意 Steve 的观点,您应该避免在模型/域类中使用 DependencyObjectDependencyProperty,并且视图模型类应该采用 INotifyPropertyChangedIDataErrorInfo 进行绑定。

      我要补充一点,在您的视图模型类中,我会避​​免使用 DependencyProperty,除了您需要在 xaml 逻辑中使用的属性,例如 DataTriggers。

      为了处理在模型层类中触发的更改,我还将引用视图模型类中的模型/域对象,并通过 getter 和 setter 传递给模型/域类,就像史蒂夫提到的那样。我要补充一点,模型/域类需要引发视图模型类需要订阅的事件,以便可以根据发生的更改在视图模型类中调用 OnPropertyChanged() 的一个或多个属性在您的业务逻辑中。

      【讨论】:

        【解决方案3】:

        首先,我不建议对视图模型或模型使用依赖属性 (DP)。 DP 是在设计时考虑了 UI 概念的属性,例如优先规则、DataContext 支持、默认值等。您不需要在视图模型中使用这些概念,因此您应该改用 INotifyPropertyChanged

        拥有一个只是传递到模型层的视图模型根本没有任何价值。所以不要这样做!你不应该仅仅因为你认为你应该在你的代码中添加层、结构或概念。简单是您应该始终追求的目标。

        因此,如果您可以实现模型层,只需将 INotifyPropertyChanged 绑定到您的视图即可。

        但是...在某些情况下,您可能无法在模型中实现INotifyPropertyChanged。例如,它可能是从 Web 服务生成的。在这种情况下,您将需要一个视图模型来执行传递功能,但还要通过INotifyPropertyChanged 添加更改通知。

        【讨论】:

        • 我对视图到模型的这种直接绑定感到很痛苦,我看到了不同的意见。原Fowler 没有直接链接。 Gossman 允许“简单示例,视图是直接绑定到模型的数据”。 Smith 强调:“视图类不知道模型类的存在。”我对此很陌生,但我的直觉更喜欢清晰的分离,不允许 View-Model 绑定。想法?
        • 虽然我同意您不应该仅仅为了它而添加层,但我不愿意将 ViewModel 视为简单的传递。在许多情况下,它可能在表面上看起来像这样(即对于编辑视图),但是 ViewModel 服务于视图,而模型应该服务于业务规则和持久性实现。 ViewModel 通过INotifyPropertyChanged 处理视图通知,并通过IDataErrorInfo 处理验证错误。域对象可能被 Web 服务使用或通过它们传输。 (即对 Silverlight 客户。)查看具体细节会妨碍您。
        猜你喜欢
        • 1970-01-01
        • 2021-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多