当前位置:  开发笔记 > 编程语言 > 正文

使用MVVM处理WPF中的对话框

如何解决《使用MVVM处理WPF中的对话框》经验,为你挑选了7个好方法。

在WPF的MVVM模式中,处理对话框是更复杂的操作之一.由于您的视图模型对视图一无所知,因此对话通信很有趣.我可以公开一个ICommand,当视图调用它时,会出现一个对话框.

有没有人知道处理对话结果的好方法?我说的是关于Windows对话框,比如MessageBox.

我们这样做的方法之一是在viewmodel上有一个事件,当需要对话框时,视图会订阅该事件.

public event EventHandler RequiresDeleteDialog;

这没关系,但这意味着视图需要代码,这是我想远离的东西.



1> Jeffrey Knig..:

我建议放弃1990年代的模态对话框,而是将控件实现为覆盖(画布+绝对定位),其中可视性与VM中的布尔值相关联.更接近ajax类型控件.

这非常有用:


如:


这是我如何实现一个用户控件.单击"x"会关闭usercontrol代码后面的一行代码中的控件.(因为我在一个dll中的.exe和ViewModels中有我的视图,所以我对操作UI的代码感到不舒服.)

Wpf对话框


是的我也喜欢这个想法,但是希望看到这个控件的一些例子,如何显示它,并从中检索对话结果等.特别是在Silverlight中的MVVM场景中.
如何防止用户与此对话框叠加层下的控件进行交互?
这种方法的问题在于你无法从第一个开启第二个模态对话框,至少在没有对叠加系统进行大量修改的情况下......
这种方法对我来说似乎很糟糕.我错过了什么?这比真正的对话框更好吗?
这种方法的另一个问题是无法移动"对话框".在我们的应用程序中,我们必须有一个可移动的对话框,以便用户可以看到它背后的内容.
"帆布+绝对定位" - 什么?为什么?在绝大多数情况下,仅仅提到"绝对定位"就是一个警告信号,表明事情是非常非常错误的.如果主窗口可以有任何大小,绝对位置将如何有用?总的来说,在我看来,这个解决方案很难复制使用变通方法的有限Web UI的每个方面,看起来它们是具有真实对话框的实际GUI.
我不知道杰弗里是否在其他地方发布了他的解决方案,但我对此进行了一次拍摄.我制作了自己的UserControl,并且像Jeffrey的XAML一样实现了它.要获得对话框结果,我使用RelayCommand并使用CommandParameters传递Yes/No结果
另一个问题是当您有两个监视器并且要将对话框拖到第二个监视器时。

2> Roubachof..:

你应该使用调解员.Mediator是一种常见的设计模式,在其某些实现中也称为Messenger.它是Register/Notify类型的范例,使您的ViewModel和Views能够通过低耦合消息传导机制进行通信.

您应该查看google WPF Disciples组,然后只搜索Mediator.你会对答案感到满意......

但是你可以从这开始:

http://joshsmithonwpf.wordpress.com/2009/04/06/a-mediator-prototype-for-wpf-apps/

请享用 !

编辑:您可以在此处查看MVVM Light Toolkit对此问题的答案:

http://mvvmlight.codeplex.com/Thread/View.aspx?ThreadId=209338


只是一句话:WPF门徒没有介绍Mediator模式,它是一种经典的GoF模式......(http://www.dofactory.com/Patterns/PatternMediator.aspx).不错的答案;)
请上帝,不要使用调解员或愚蠢的信使.除非你能以某种方式记住整个代码库中订阅和处理每个事件的所有点,否则这种带有大量消息的代码变得非常难以调试.它成为新开发者的噩梦.事实上,我认为整个MvvMLight库是一个庞大的反模式,因为它普遍和不必要地使用异步消息传递.解决方案很简单:调用您设计的单独对话服务(即IDialogService).该接口具有回调的方法和事件.
Marlon grech刚刚发布了一个全新的调解员实现:http://marlongrech.wordpress.com/2009/04/16/mediator-v2-for-mvvm-wpf-and-silverlight-applications/

3> 小智..:

一个好的MVVM对话框应该:

    仅使用XAML声明.

    从数据绑定中获取所有这些行为.

不幸的是,WPF不提供这些功能.显示对话框需要对ShowDialog()进行代码隐藏调用.支持对话框的Window类不能在XAML中声明,因此不能轻易地将数据绑定到DataContext.

为了解决这个问题,我编写了一个XAML存根控件,它位于逻辑树中,并将数据绑定中继到一个Window并处理显示和隐藏对话框.您可以在这里找到它:http://www.codeproject.com/KB/WPF/XAMLDialog.aspx

它只是简单地使用,并且不需要对ViewModel进行任何奇怪的更改,也不需要事件或消息.基本调用如下所示:


您可能想要添加一个设置显示的样式.我在我的文章中解释它.我希望这可以帮助你.


对于在MVVM中显示对话框窗口的问题,这是一种非常有趣的方法。
`"显示一个对话框需要一个代码隐藏"`mmm你可以在ViewModel中调用它

4> blindmeis..:

我使用这种方法与MVVM进行对话.

我现在要做的就是从我的视图模型中调用以下内容.

var result = this.uiDialogService.ShowDialog("Dialogwindow title goes here", dialogwindowVM);



5> Roboblob..:

我目前的解决方案解决了您提到的大多数问题,但它完全从平台特定事物中抽象出来,可以重复使用.此外,我没有使用代码隐藏仅与实现ICommand的DelegateCommands绑定.Dialog基本上是一个View - 一个单独的控件,它有自己的ViewModel,它从主屏幕的ViewModel显示,但是通过DelagateCommand绑定从UI触发.

在此处查看完整的Silverlight 4解决方案与MVVM和Silverlight 4的模态对话框



6> Mike Rowley..:

在学习(仍在学习)MVVM时,我真的很挣这个概念.我决定了什么,以及我认为其他人已经决定但我不清楚的是:

我最初的想法是不应该允许ViewModel直接调用对话框,因为它没有业务决定对话框应该如何显示.因此我开始考虑如何传递消息,就像我在MVP中那样(即View.ShowSaveFileDialog()).但是,我认为这是错误的做法.

ViewModel可以直接调用对话框.但是,当您测试ViewModel时,这意味着对话框将在测试期间弹出,或者一起失败(从未真正尝试过).

因此,需要进行的是测试是使用对话框的"测试"版本.这意味着,对于您拥有的对话框,您需要创建一个接口,并模拟对话框响应或创建一个具有默认行为的测试模拟.

您应该已经使用某种服务定位器或IoC,您可以根据上下文为您提供正确的版本.

使用这种方法,您的ViewModel仍然是可测试的,并且根据您模拟对话框的方式,您可以控制行为.

希望这可以帮助.



7> Chris Bordem..:

有两种很好的方法可以做到这一点,1)对话服务(简单,干净),2)视图辅助.View辅助提供了一些简洁的功能,但通常不值得.

对话服务

a)一个对话框服务接口,如via构造函数或一些依赖容器:

interface IDialogService { Task ShowDialogAsync(DialogViewModel dlgVm); }

b)您的IDialogService实现应该打开一个窗口(或将一些控件注入活动窗口),创建一个对应于给定dlgVm类型名称的视图(使用容器注册或约定或具有相关DataTemplates类型的ContentPresenter).ShowDialogAsync应该创建一个TaskCompletionSource并返回它的.Task proptery.当您想要关闭时,DialogViewModel类本身需要一个可以在派生类中调用的事件,并在对话框视图中观察以实际关闭/隐藏对话框并完成TaskCompletionSource.

b)要使用,只需在您的某个DialogViewModel派生类的实例上调用await this.DialogService.ShowDialog(myDlgVm).等待返回后,查看您在对话框VM上添加的属性,以确定发生了什么; 你甚至不需要回调.

查看协助

这使您可以在viewmodel上监听事件.这可以全部包含在混合行为中,以避免代码落后和资源使用,如果你是如此倾向(FMI,子类"行为"类,以在类固醇上看到一种Blendable附加属性).现在,我们将在每个视图上手动执行此操作:

a)使用自定义有效负载(DialogViewModel派生类)创建OpenXXXXXDialogEvent.

b)让视图在其OnDataContextChanged事件中订阅该事件.如果旧值!= null并且在Window的Unloaded事件中,请务必隐藏和取消订阅.

c)当事件触发时,让视图打开您的视图,该视图可能位于页面上的资源中,或者您可以按照惯例在其他位置找到它(例如在对话框服务方法中).

这种方法更灵活,但需要更多工作才能使用.我不太用它.例如,一个很好的优点是能够将视图物理地放置在选项卡中.我已经使用算法将其放在当前用户控件的边界中,或者如果不够大,则遍历可视树,直到找到足够大的容器.

这允许对话框靠近他们实际使用的位置,只调暗与当前活动相关的应用程序部分,让用户在应用程序中移动而不必手动推送对话框,甚至有多个准对象模式对话框在不同的选项卡或子视图上打开.

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有