在WPF中使用MVVM,我应该从后面的View代码或ViewModel启动子窗口吗?

She*_*dan 18 wpf view mvvm childwindow viewmodel

我有一段时间对此感到困惑.我正在RibbonWindow使用MVVM模式编写相当大的WPF应用程序.屏幕RibbonBar顶部有一个菜单,其余部分显示各种视图.某些视图包含其他视图,其中一些视图具有启动子窗口的按钮.

到目前为止,我一直在使用View代码隐藏文件执行此操作,但我知道在使用MVVM时这些文件应该是空的.我可以将子窗口启动代码移动到ViewModel,但是我需要一个对main的引用RibbonWindow(设置为子窗口所有者),这似乎不正确.

关于如何使用MVVM正常实现这一建议或提示将不胜感激.

Mat*_*est 20

我通常通过创建某种WindowViewLoaderService来处理这个问题.当您的程序初始化时,您使用以下代码注册Window和ViewModel:

WindowViewLoaderService.Register(TypeOf(MainWindowView), TypeOf(MainWindowViewModel));
WindowViewLoaderService.Register(TypeOf(MyWindowView), TypeOf(MyWindowViewModel));
Run Code Online (Sandbox Code Playgroud)

然后,当您可以从ViewModel调用此服务时,您需要引用的只是另一个ViewModel.例如,如果您在MainWindowViewModel中,则可能具有以下代码:

var myChildWindowVM = new MyWindowViewModel();
WindowViewLoaderService.ShowWindow(myChildWindowVM);
Run Code Online (Sandbox Code Playgroud)

然后,WindowViewLoaderService将查找与您传递的指定ViewModel关联的View.它将创建View,将其DataContext设置为您传入的ViewModel,然后显示View.

这样您的ViewModels就不会知道任何视图.

您可以非常轻松地推出自己的其中一项服务.它需要做的就是保持一个Dictionary,键是ViewModelType,值是ViewType.Register方法添加到您的字典中,ShowWindow方法根据传入的ViewModel查找正确的视图,创建视图,设置DataContext,然后在其上调用Show.

大多数MVVM框架为您提供开箱即用的功能.例如,Caliburn有一个光滑的,只使用命名约定,在本框架中称为ViewLocator.这是一个总结的链接:http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/04/mvvm-study-segue-introducing-caliburn-micro.aspx

另一方面,Cinch将其称为WPFUIVisualizerService,您可以在此处看到:http: //www.codeproject.com/KB/WPF/CinchIII.aspx

这些应该有助于你滚动.


Abd*_*men 6

好吧,开头的一句话是,"在代码隐藏中没有代码全部"实际上是一个"神话".如果你想要务实,并且你看到拥有一些代码(尽可能少会更好),会让你的生活更轻松并解决你的问题,那么你应该坚持下去.

但是,在这种情况下,实际上有一些松散耦合的方法来做到这一点.您可以拥有一个为您进行交互的服务.您从ViewModel启动与用户的交互,服务负责(例如通过显示ChildWindow),并返回用户的响应.可以轻易地模拟该服务以进行测试.它可以单独测试.

也就是说,如果你想自己做事.如果您想要一个框架来为您做繁重的工作,您可以查看PrismInteractionRequest提供的功能.这是MSDN文章,讨论了高级MVVM场景,其中包括一个关于用户交互模式的部分.这就是我的方式,它非常简单,优雅和直接.

希望这可以帮助 :)