5

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

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

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

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

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

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

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

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

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

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

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

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

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

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

我的问题:

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

3 回答 3

1

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

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

于 2012-11-26T22:10:29.620 回答
0

我同意史蒂夫的观点,你应该避免在你的模型/域类中使用DependencyObjectDependencyProperty,并且视图模型类应该采用INotifyPropertyChangedIDataErrorInfo用于绑定目的。

我会在您的视图模型类中添加这一点,我会避免使用DependencyProperty您需要在 xaml 逻辑中使用的属性,例如DataTriggers。

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

于 2012-11-27T02:52:12.197 回答
0

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

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

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

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

于 2012-11-27T06:25:22.510 回答