MVVM:如何处理嵌套的ViewModel之间的交互?
我一直在尝试经常提到的MVVM模式,在某些情况下我很难定义明确的边界。 在我的应用程序中,我有一个对话框,允许我创建到Controller的连接。 对话框有一个ViewModel类,这个类很简单。 但是,该对话框还包含一个附加控件(由ContentTemplateSelector
选择),该控件根据所连接的Controller的特定类型而有所不同。 此控件具有自己的ViewModel。
我遇到的问题是,当我按OK键关闭对话框时,我需要实际创建请求的连接,这需要在内部Controller特定的ViewModel类中捕获的信息。 简单地让所有特定于Controller的ViewModel类实现构建连接的公共接口是很诱人的,但是内部ViewModel是否应该真正负责这种构造?
我的一般问题是:ViewModel应该如何与彼此交互,是否有任何普遍接受的设计模式,特别是当’父’VM需要来自’子’VM的帮助以便知道该怎么做?
编辑:
我确实想出了一个比我原先想象的更清洁的设计,但我仍然不确定这是否是“正确”的方式。 我有一些后端服务,允许ContentTemplateSelector查看Controller实例并伪神奇地找到要为连接构建器显示的控件。 让我烦恼的是我的顶级ViewModel必须查看生成的控件的DataContext
并将其转换为适当的界面,这似乎是个坏主意(为什么View的DataContext
与创建有关?连接?)
我结束了这样的事情(简化):
public interface IController { IControllerConnectionBuilder CreateConnectionBuilder(); } public interface IControllerConnectionBuilder { ControllerConnection BuildConnection(); }
我有我的内部ViewModel类实现IControllerConnectionBuilder
,Controller返回内部ViewModel。 然后,顶级ViewModel可视化此IControllerConnectionBuilder
(通过伪魔法机制)。 它仍然困扰我一点,这是我的内部ViewModel执行构建,但至少现在我的顶级ViewModel不必知道脏细节(它甚至不知道或不关心可视化控件正在使用视图模型)。
如果有办法进一步清理它,我欢迎其他想法。 我仍然不清楚ViewModel有多少责任“好”。
适用于视图模型之间交互的选项是直接绑定到位于viewmodel类之间的观察者类。
我想你想让你的顶级ViewModel
意识到NestedViewModel
的存在,从层次结构的角度来看,主视图包含了子视图。
在我看来,你的直觉是正确的,嵌套的ViewModel暴露由顶级用户操作启动的行为感觉不正确。 相反,顶级ViewModel
应该为与其关联的视图提供行为。
但我考虑将连接构造的责任转移到ICommand
,并通过顶级ViewModel
公开此命令。 然后,主对话框上的OK按钮将绑定到此命令,该命令将委托给顶级ViewModel
,例如,在执行时调用ViewModel.CreateConnection()
。
然后,嵌套控件的责任纯粹是将数据收集并公开给它的NestedViewModel
,供包含的ViewModel
,理论上它在不同的上下文中更易于重用,需要输入相同的信息(如果有的话) – 让我们说你想重新用它来编辑已经创建的连接。
如果不同类型的NestedViewModel
暴露出完全不同的数据集,那么唯一的问题就是如此。
例如,一个将HostName和Port公开为属性,另一个公开UserName和Password 。
在这种情况下,您可能需要执行一些基础结构工作,以使您的顶级ViewModel.CreateConnection()
仍然以干净的方式工作。 虽然如果你有少量的嵌套控件类型,它可能不值得努力,并且一个简单的NestedViewModel
类型检查和NestedViewModel
就足够了。
这听起来可行吗?
我最近尝试使用Unity(Microsoft Enterprise库)来使用dependency injection。 当使用完全定义两个视图模型彼此不需要的接口时,这可能是一条路。 MEF将是我所知道的dependency injection的另一种选择。
HTH