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