帮助处理复杂的MVVM(多个视图)


18

我需要在以下情况下创建视图模型的帮助:

  1. 深层次数据
  2. 同一数据集的多个视图
  3. 每个视图都是基于活动选择的单个动态变化的视图
  4. 根据属性的值,在选项卡控件中显示不同类型的选项卡

在此处输入图片说明

我的问题:

我应该为每个视图(VM1,VM2等)创建视图模型表示吗?

1. Yes:
    a. Should I model the entire hierarchical relationship? (ie, SubVM1, HouseVM1, RoomVM1)
    b. How do I keep all hierarchies in sync? (e.g, adding/removing nodes)

2. No:
    a. Do I use a huge, single view model that caters for all views?

这是单个视图的示例

图1:根据活动房间更新了多个视图。注意选项卡控件

在此处输入图片说明

图2:不同的活动室。多个视图已更新。选项卡控件项根据对象的属性进行了更改。

在此处输入图片说明

图3:不同的选择类型。整个视图更改

在此处输入图片说明


顺便说一句,穆利观点是什么?错字?
JensG 2014年

“木里观”是一个错字。对于同一模型/视图模型,我的意思是不同的视图。我的问题是,我应该为每个视图重新建模/包装整个模型层次结构,以便每个视图模型仅包含单个视图所需的内容吗?还是应该创建一个包含所有视图属性的单一视图模型层次结构?自从我发布了这个问题以来,我很(不幸)很不幸地发现了两者的利弊。一旦事情变得不那么忙碌,以后将在完全诊断我的经验的情况下更新此线程。
jayars

请记住,设计规则是先展示一般事物,然后再深入细节。它将为您带来明亮的视图,如果用户更深入,则会出现新的视图。因此请分开使用小视图和ViewModel。检查本文设计用户界面
Csharls

@jsjslim当我阅读“保持所有层次结构同步”时,我不寒而栗。我怀疑您选择了多视图,但我怀疑您对此感到后悔(但之前我做错了)。为了其他可能有相同问题的读者,您至少可以给我们一个快速的答案吗?
Guy Schalnat 2014年

2
@ guy-schalnat多视图是必需的。我的问题是试图弄清楚如何构建视图模型。该项目仍在进行中,我找不到时间编写完整的分析。但总而言之:我应该忽略模型结构,而只关注视图。我遇到的复杂性是自我强加的:我想非常糟糕地使用WPF的数据绑定,因此被解决。最后,我所做的是好的,旧的“复制/粘贴/重构”。出现的最终设计是轻量级的(很少重复),更重要的是可以工作。将来会写出完整的分析。
jayars 2014年

Answers:


13

要回答这个问题,是的,每个视图都应该有自己的视图模型。但是,无需对整个层次结构建模。只有视图需要的。

我在有关MVVM的大多数在线资源中遇到的问题是:

在大多数示例中,视图几乎是模型的一对一映射。但是在我的场景中,对于同一模型的不同方面存在不同的观点,我发现自己陷入了两种选择之间:

所有其他视图模型都使用的一个整体视图模型

在此处输入图片说明

或每个视图一个视图模型

在此处输入图片说明

但是两者都不理想。

面向模型的视图模型(MVM)虽然代码重复性较低,但却是维护的噩梦

面向视图的视图模型(VVM)为每个视图生成高度专业的类,但包含重复项。

最后,我决定每个View拥有一个VM易于维护和编写代码,因此我选择了VVM方法。

代码正常工作后,我开始将所有通用属性和操作重构为当前的最终形式:

在此处输入图片说明

在此最终形式中,公共视图模型类组成了每个VVM。

当然,我仍然必须决定什么被认为是通用/专业。并且当添加/合并/删除视图时,此平衡会更改。

但是,这样做的好处是,我现在能够轻松地将成员从通用切换到VVM,反之亦然。

关于保持对象同步的简要说明:

拥有一个通用视图模型可以解决大多数问题。每个VVM都可以简单地引用相同的Common View模型。

我也倾向于从简单的回调方法开始,如果需要多个侦听器,则逐渐发展为事件/观察者。

对于非常复杂的事件(例如,意外的级联更新),我将转而使用调解器。

我不回避孩子对父代有反向引用的代码。使代码正常工作的一切。

如果出现重构的机会,我会抓住机会。

我吸取的教训:

  1. 丑/工作代码>美丽/非工作代码
  2. 合并多个小类比拆分一个大类要容易

我希望我可以投票两次。这是我所见选项的最清晰的解释之一。
聪明的人

3

查看您的模型,我绝对会建议创建ViewModel的层次结构和许多小View。您很可能必须对原始层次结构进行建模。

为了使视图模型之间保持同步,请使用事件,或者在视图模型之间具有彼此的属性。View和ViewModel之间的同步应该是标准的通知属性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.