我的模型由一个主要对象组成,用户也可以添加其他各种对象。添加的对象存储在主对象中包含的List<object>
中,并且是相关的子对象。
所以如果这个项目是一个房子。用户可以向房屋添加许多Room
个对象,这些对象存储在List<Room> RoomList
中。然后,每个Room
可以再次添加Furnishings
个List<Furnishing> FurnishingsList
个ObservableCollection
问题是如何在MVVM方法中实现这一点?当用户添加新对象时,我是否将其添加到ViewModel中的Furnishings
,以便更新视图并同时将其添加到连接到VM的模型中?或者我将它存储在VM中直到保存或提交命令,然后将其传递给模型?
在我的例子中,我有各种编辑器(每个都是用户控件)。因此,用户可以在高级别编辑房屋,使用一个编辑器添加,编辑和移除房屋中的房间。而且,在较低级别,使用不同的编辑器编辑每个房间,添加和删除EditRoomModelView
。
所以当用户'编辑'一个房间说。我生成一个Room
,其中包含{{1}}。用户添加,编辑和操纵该房间的家具。
在每个命令中,最好同步模型和ModelViee中的数据,如上所述。或者我将更改直接推送到模型中,并让ViewModel仅提供注入的Model属性的getter。但是,这种方式将对象添加到模型列表不会更新视图。我真的必须同时将数据添加到ModelView和Model中,所以一切都处于相同的状态。
漫不经心的考虑,努力寻找一个好的方法,任何人都能理解我的目标?
答案 0 :(得分:3)
我不确定是否有一个好的答案。听起来好像你在讨论如何保持连贯性 - 你是否有一个来自表示层的简单传递方案,或者你是否介入用户请求并在那里有逻辑。
事实上,如果是这个问题,有各种因素在起作用。您更喜欢在表示层中进行验证吗?应用程序有多复杂,需要具有多大的可扩展性?您的视图模型是否需要在多个位置访问?
所以,考虑到所有这些,我可以告诉你我个人更喜欢接近这个问题(具体来说,你提到的添加问题)。我通常喜欢创建视图模型来描述用户关注的问题,例如EditItemViewModel<T>
或ListViewModel<T>
。因此,在GUI中,会有某种类型的房间列表框绑定到ListViewModel<Room>
。这个VM显然会公开一个可观察的集合,还有Add,Delete,Edit的命令。
因此,从我的角度来看,此VM将要执行的表示层,视图模型化的东西是路由请求以解决其他GUI问题。如果单击“添加”以添加房间,则此VM负责通过命令为任何屏幕/窗口/任何房间添加所需的内容启动请求,该房间将具有自己的VM。在接收到添加请求时,该VM将生成的数据传输对象向下传递到将进行验证的域以及任何必要的域操作。我通常通过服务层处理这个问题。现在,如果域操作成功,服务层将引发某种偶数或回调,以使列表VM知道存在更改。发生这种情况时,列表VM会重新查询其服务并相应地更新其可观察集合。现在,您的GUI与所有域都是一致的。
我赞成这种分层方法的原因是所有业务逻辑都发生在GUI“下方”的某个位置,而GUI不需要关注这种情况。从概念上讲,GUI只是说“在这里,域层,用户想要添加它 - 做所有这些,并让任何感兴趣的GUI组件知道你什么时候完成,以便他们可以刷新自己”。
与简单的传递方案或VM只是重新公开某些模型对象的属性的方案相比,我在这里描述的内容自然会产生一些开销。但是,就个人而言,我认为从解耦角度获得的优势是值得的,特别是在扩展应用程序时。它使您能够从根本上改变域模型的内部交互,而无需更改表示层代码。
答案 1 :(得分:2)
首先:View
是DataModel
的镜像,因此始终将首先添加到Model
并且只有在思考之后如果它推进Vm
或View
。
第二:ViewModel
是将Model
与View
连接起来的桥梁,但并不意味着它必须以相同的方式构建Model
。如果要向用户显示所有子集合,则必须像属性一样公开它们,并在parent-child
或VM
中只有“原始”集合内部构建VM
关系。在DataModel
中有它们之间的有效关系。
答案 2 :(得分:2)
从您描述的应用程序中,听起来您的视图模型层不会显着修改或塑造您的模型。所以,我会在包装的模型对象上创建各种视图模型属性setter / getters简单适配器。这样,当视图模型发生变化时,您的模型将立即更新。
但是......如果你需要提供'取消'功能,即用户打开一个模态表格来编辑某些视图模型,但是然后取消而不是OK编辑,这个简单的方法将无效。
您提交模型层的时间很少会产生太大影响,因为这通常不是一个耗时的过程。更重要的是模型状态持续存在时。这通常由显式调用save命令触发,该命令将模型发送到持久性服务(文件/云等...)