在WPF MVVM中打开对话框

时间:2009-11-26 21:37:56

标签: wpf mvvm dialog

我有一个应用程序,需要从用户输入一些信息的按钮打开一个对话框。

目前我这样做(效果很好)

  • 按钮单击会在ViewModel中生成一个命令。
  • ViewModel引发Controller侦听的事件。
  • Controller会计算出新窗口的详细信息(例如View,ViewModel& model)并打开它(ShowDialog)
  • 当窗口关闭时,Controller会将结果添加到eventargs并返回ViewModel
  • ViewModel将信息传递给模型。

有很多步骤,但它们都有意义,而且没有太多的打字。

代码如下(窗口要求输入用户名)

视图模型:

AskUserNameCommand = DelegateCommand(AskUserNameExecute);
...

public event EventHandler<AskUserEventArgs> AskUserName;

void AskUserNameExecute(object arg) {
    var e = new AskUserNameEventArgs();
    AskUserName(this, e);
    mModel.SetUserName(e.UserName);
}

控制器:

mViewModel.AskUserName += (sender,e) => {
    var view = container.Resolve<IAskUserNameView>();
    var model = container.Resolve<IAskUserNameModel>();
    var viewmodel = container.Resolve<IAskUserNameViewModel>(view, model);
    if (dlg.ShowDialog() ?? false)
        e.UserName = model.UserName;
}

我的问题是水平通信如何在MVVM模式中工作。 不知何故,让控制器参与模型之间的数据传输似乎是错误的。

我已经查看了中介模式,让模型直接进行通信。不喜欢这个想法,因为它使模型取决于GUI的实现细节。 (即如果用文本框替换对话框,模型需要更改)

5 个答案:

答案 0 :(得分:12)

由于某种原因,我不喜欢目前的大多数建议,所以我想我会将一个几乎相同的问题链接到我的答案:

Open File Dialog MVVM

具体来说,Cameron MacFarland的回答正是我所做的。通过界面提供的服务提供IO和/或用户互动是可以使用的方式,原因如下

  • 可以测试
  • 它抽象出任何对话框的实现,以便您可以在不影响组成代码的情况下更改处理这些类型的事物的策略
  • 不依赖任何沟通模式。你看到很多建议都依赖于调解器,比如Event Aggregator。这些解决方案依赖于与调解员另一方的合作伙伴实现双向沟通,这种沟通既难以实施,也非常宽松。
  • ViewModels保持自治。我和你一样,在控制器和ViewModel之间进行通信时感觉不对。如果没有其他原因这样可以减轻可测试性,ViewModel应该保持自治。

希望这有帮助。

答案 1 :(得分:2)

我使用this方法与mvvm对话。

我现在所做的就是从我的viewmodel调用以下内容来处理对话框。

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

答案 2 :(得分:0)

我遇到过类似的问题。这就是我如何解决它们,以及为什么我已经完成了我所做的事情。

我的解决方案:

我的MainWindowViewModel有一个名为Modal的ModalViewModelBase类型的属性。 如果我的代码需要某个视图是模态的,它会在此属性中引用它。 MainWindowView通过INotifyPropertyChanged机制监视此属性。如果将Modal设置为某个VM,则MainWindowView类将获取VM并将其放入ModalView窗口,其中将通过DataTemplates的魔术显示相应的UserControl,该窗口使用ShowDialog显示。 ModalViewModelBase具有DialogResult的属性和名为IsFinished的属性。当模式VM将IsFinished设置为true时,视图将关闭。

我也有一些特殊的技巧来处理想要询问用户输入的后工作者线程这样的交互式内容。

我的推理:

模态视图的原理是禁用其他视图,同时显示模态。这是View的逻辑的一部分,基本上是无形的。这就是我在MainWindowViewModel中拥有它的属性的原因。我要更进一步,我应该为主VM中的所有其他VM做出所有其他属性或命令抛出异常,而在模态模式下,但我觉得这是过度的。

实际上拒绝用户任何其他操作的View机制,不必使用弹出窗口和sho​​wdialog执行,可能是您将模态视图放在现有窗口中,但禁用所有其他操作,或其他一些操作事情。此视图相关逻辑属于视图本身。 (一个典型的设计师无法为这个逻辑编码,这似乎是次要问题。我们都需要一些帮助。)

这就是我如何做到的。我只提供它作为一个建议,可能有其他的思考方式,我希望你也得到更多的回复。

答案 3 :(得分:0)

我在类似场景中使用过Prism v2的EventAggregator。关于prims的好处是,您不必在MVVM应用程序中使用整个框架。您可以提取EventAggregator功能并将其与当前设置一起使用。

答案 4 :(得分:0)

您可以查看此MVVM文章。它描述了控制器如何与ViewModel通信:

http://waf.codeplex.com/wikipage?title=Model-View-ViewModel%20Pattern&ProjectName=waf