在WPF MVVM中打开对话框

adr*_*anm 13 wpf dialog mvvm

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

目前我这样做(工作正常)

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

有很多步骤,但它们都有意义,并没有太多的打字.

代码看起来像这样(窗口要求输入用户名)

视图模型:

AskUserNameCommand = DelegateCommand(AskUserNameExecute);
...

public event EventHandler<AskUserEventArgs> AskUserName;

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

控制器:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

And*_*mes 14

我最不喜欢的一个原因或其他当前的建议,所以我想我会链接到与我的答案几乎相同的问题一样:

打开文件对话框MVVM

具体来说,Cameron MacFarland的回答正是我所做的.通过接口提供的服务提供IO和/或用户交互是这里的方法,原因如下:

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

希望这可以帮助.


Gug*_*uge 0

我也遇到过类似的问题。以下是我解决这些问题的方法,以及我这样做的原因。

我的解决方案:

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

我还有一些特殊的技巧,可以从想要要求用户输入的后台工作线程中执行此类交互操作。

我的推理:

模态视图的原理是禁用其他视图,而显示模态视图。这是视图逻辑的一部分,本质上是无外观的。这就是为什么我在 MainWindowViewModel 中有一个属性。如果我要更进一步,我应该让主虚拟机中所有其他虚拟机的所有其他属性或命令在模态模式下抛出异常,但我觉得这太过分了。

实际上拒绝用户任何其他操作的视图机制不必通过弹出窗口和显示对话框来执行,可能是您将模式视图放在现有窗口中,但禁用所有其他窗口或其他一些东西。这个与视图相关的逻辑属于视图本身。(典型的设计师无法为这种逻辑编写代码,这似乎是次要的问题。有时我们都需要帮助。)

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