MVVM中的ViewModel应该引用View吗?

Joh*_*han 13 wpf design-patterns mvvm

在MVVM(Model-View-ViewModel)模式中,ViewModel应该引用视图.我认为不应该.但是下面的场景应该如何处理呢?我有一个视图,其中有一个选项卡控件作为主容器,此视图的viewmodel实现了一个命令,用于向选项卡控件添加新选项卡.简单的方法是允许viewmodel引用视图,然后在命令实现中以编程方式将新选项卡添加到视图中的tabcontrol.这似乎是错的.我应该以某种方式将tabcontrol绑定到viewmodel,然后实现数据/控件模板以添加新选项卡.我希望这对某人有点意义:)

Ree*_*sey 13

在"纯粹的"MVVM中,ViewModel不应该真正引用View.但是,在View中提供某种形式的界面通常很方便,ViewModel可以与它进行交互.

但是,我发现我几乎再也不会这样做了.另一种方法是在View中使用某种形式的附加属性或混合行为,并将其绑定到ViewModel属性.这允许您在视图中保持视图逻辑100%.此外,通过为此创建行为,您可以创建可重用的类型,可用于在每个ViewModel-> View交互中处理此问题.我非常喜欢这种方法,而不是ViewModel中的任何View逻辑.

为了演示这种技术,我为表达式代码库编写了一个名为WindowCloseBehavior的示例.它演示了如何在视图中使用View中绑定到ViewModel属性的行为来处理控制Window的生命周期,包括防止它被关闭等.


Joh*_*wen 8

Reed和Dan介绍了一般方法,但是在参考您的具体情况时,TabControl是一个ItemsControl,因此可以将其ItemsSource绑定到ViewModel中的数据集合,该数据集合表示要显示的选项卡集.然后,每种类型的选项卡的UI可以由特定于项的数据类型的DataTemplate表示(使用DataType或DataTemplateSelector).然后,您可以根据需要从VM添加或删除数据项,并自动更新选项卡,而无需VM了解TabControl的任何信息.


Dan*_*ant 6

我发现在视图上公开处理特定于视图的功能的接口通常是一种有用的折衷方案。这是处理纯绑定难以完成的事情的好方法,例如指示表单关闭、打开文件对话框(尽管这通常放在其自己的服务接口中)或与未针对数据设计良好的控件进行交互绑定(例如您提供的示例。)

使用接口仍然可以使 View 和 ViewModel 在很大程度上解耦,并使您能够在测试期间模拟特定的 IView。