Ray*_*sen 232 .net wpf design-patterns dialog mvvm
在WPF的MVVM模式中,处理对话框是更复杂的操作之一.由于您的视图模型对视图一无所知,因此对话通信很有趣.我可以公开一个ICommand,当视图调用它时,会出现一个对话框.
有没有人知道处理对话结果的好方法?我说的是关于Windows对话框,比如MessageBox.
我们这样做的方法之一是在viewmodel上有一个事件,当需要对话框时,视图会订阅该事件.
public event EventHandler<MyDeleteArgs> RequiresDeleteDialog;
Run Code Online (Sandbox Code Playgroud)
这没关系,但这意味着视图需要代码,这是我想远离的东西.
Jef*_*ght 131
我建议放弃1990年代的模态对话框,而是将控件实现为覆盖(画布+绝对定位),其中可视性与VM中的布尔值相关联.更接近ajax类型控件.
这非常有用:
<BooleanToVisibilityConverter x:Key="booltoVis" />
Run Code Online (Sandbox Code Playgroud)
如:
<my:ErrorControl Visibility="{Binding Path=ThereWasAnError, Mode=TwoWay, Converter={StaticResource booltoVis}, UpdateSourceTrigger=PropertyChanged}"/>
Run Code Online (Sandbox Code Playgroud)
这是我如何实现一个用户控件.单击"x"会关闭usercontrol代码后面的一行代码中的控件.(因为我在一个dll中的.exe和ViewModels中有我的视图,所以我对操作UI的代码感到不舒服.)

Rou*_*hof 51
你应该使用调解员.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
小智 29
一个好的MVVM对话框应该:
不幸的是,WPF不提供这些功能.显示对话框需要对ShowDialog()进行代码隐藏调用.支持对话框的Window类不能在XAML中声明,因此不能轻易地将数据绑定到DataContext.
为了解决这个问题,我编写了一个XAML存根控件,它位于逻辑树中,并将数据绑定中继到一个Window并处理显示和隐藏对话框.您可以在这里找到它:http://www.codeproject.com/KB/WPF/XAMLDialog.aspx
它只是简单地使用,并且不需要对ViewModel进行任何奇怪的更改,也不需要事件或消息.基本调用如下所示:
<dialog:Dialog Content="{Binding Path=DialogViewModel}" Showing="True" />
Run Code Online (Sandbox Code Playgroud)
您可能想要添加一个设置显示的样式.我在我的文章中解释它.我希望这可以帮助你.
bli*_*eis 23
我使用这种方法与MVVM进行对话.
我现在要做的就是从我的视图模型中调用以下内容.
var result = this.uiDialogService.ShowDialog("Dialogwindow title goes here", dialogwindowVM);
Run Code Online (Sandbox Code Playgroud)
Rob*_*lob 16
我目前的解决方案解决了您提到的大多数问题,但它完全从平台特定事物中抽象出来,可以重复使用.此外,我没有使用代码隐藏仅与实现ICommand的DelegateCommands绑定.Dialog基本上是一个View - 一个单独的控件,它有自己的ViewModel,它从主屏幕的ViewModel显示,但是通过DelagateCommand绑定从UI触发.
在此处查看完整的Silverlight 4解决方案与MVVM和Silverlight 4的模态对话框
在学习(仍在学习)MVVM时,我真的很挣这个概念.我决定了什么,以及我认为其他人已经决定但我不清楚的是:
我最初的想法是不应该允许ViewModel直接调用对话框,因为它没有业务决定对话框应该如何显示.因此我开始考虑如何传递消息,就像我在MVP中那样(即View.ShowSaveFileDialog()).但是,我认为这是错误的做法.
ViewModel可以直接调用对话框.但是,当您测试ViewModel时,这意味着对话框将在测试期间弹出,或者一起失败(从未真正尝试过).
因此,需要进行的是测试是使用对话框的"测试"版本.这意味着,对于您拥有的对话框,您需要创建一个接口,并模拟对话框响应或创建一个具有默认行为的测试模拟.
您应该已经使用某种服务定位器或IoC,您可以根据上下文为您提供正确的版本.
使用这种方法,您的ViewModel仍然是可测试的,并且根据您模拟对话框的方式,您可以控制行为.
希望这可以帮助.
使用可冻结命令
<Grid>
<Grid.DataContext>
<WpfApplication1:ViewModel />
</Grid.DataContext>
<Button Content="Text">
<Button.Command>
<WpfApplication1:MessageBoxCommand YesCommand="{Binding MyViewModelCommand}" />
</Button.Command>
</Button>
</Grid>
Run Code Online (Sandbox Code Playgroud)
<Grid>
<Grid.DataContext>
<WpfApplication1:ViewModel />
</Grid.DataContext>
<Button Content="Text">
<Button.Command>
<WpfApplication1:MessageBoxCommand YesCommand="{Binding MyViewModelCommand}" />
</Button.Command>
</Button>
</Grid>
Run Code Online (Sandbox Code Playgroud)
有两种很好的方法可以做到这一点,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)当事件触发时,让视图打开您的视图,该视图可能位于页面上的资源中,或者您可以按照惯例在其他位置找到它(例如在对话框服务方法中).
这种方法更灵活,但需要更多工作才能使用.我不太用它.例如,一个很好的优点是能够将视图物理地放置在选项卡中.我已经使用算法将其放在当前用户控件的边界中,或者如果不够大,则遍历可视树,直到找到足够大的容器.
这允许对话框靠近他们实际使用的位置,只调暗与当前活动相关的应用程序部分,让用户在应用程序中移动而不必手动推送对话框,甚至有多个准对象模式对话框在不同的选项卡或子视图上打开.