在 WPF MVVM 中打开对话框
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1805778/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Open dialog in WPF MVVM
提问by adrianm
I have an application that need to open a dialog from a button where the user enters some information.
我有一个应用程序需要从用户输入一些信息的按钮打开一个对话框。
At the moment I do it like this (which works fine)
目前我是这样做的(效果很好)
- The button click generates a command in the ViewModel.
- The ViewModel raises an event which the Controller listens to.
- The Controller works out the details of the new window (i.e. View, ViewModel & model) and opens it (ShowDialog)
- When the window is closed the Controller adds the result to the eventargs and returns to the ViewModel
- The ViewModel passes the information to the Model.
- 单击按钮会在 ViewModel 中生成一个命令。
- ViewModel 引发控制器侦听的事件。
- 控制器计算出新窗口的细节(即视图、视图模型和模型)并打开它(ShowDialog)
- 当窗口关闭时,Controller 将结果添加到 eventargs 并返回到 ViewModel
- ViewModel 将信息传递给 Model。
There are a lot of steps but they all make sense and there is not much typing.
有很多步骤,但它们都有意义,而且打字不多。
The code looks like this (the window asks for the user's name)
代码如下(窗口要求输入用户名)
ViewModel:
视图模型:
AskUserNameCommand = DelegateCommand(AskUserNameExecute);
...
public event EventHandler<AskUserEventArgs> AskUserName;
void AskUserNameExecute(object arg) {
var e = new AskUserNameEventArgs();
AskUserName(this, e);
mModel.SetUserName(e.UserName);
}
Controller:
控制器:
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;
}
My question is how the horizontal communication works in the MVVM pattern. Somehow it seems wrong to let the controller be involved in the data transfer between the models.
我的问题是水平通信如何在 MVVM 模式中工作。不知何故,让控制器参与模型之间的数据传输似乎是错误的。
I have looked at the mediator pattern to let the models communicate directly. Don't like that idea since it makes the model depending on implemetations details of the GUI. (i.e. if the dialog is replaced with a textbox, the model need to change)
我已经查看了调解器模式,让模型直接进行通信。不喜欢这个想法,因为它使模型依赖于 GUI 的实现细节。(即如果对话框被替换为文本框,则模型需要更改)
回答by Anderson Imes
I don't like most of the current suggestions for one reason or another, so I thought I would link to a nearly identical question with answers I dolike:
我最不喜欢的一个原因或其他当前的建议,所以我想我会链接到一个几乎相同的问题的答案我做这样的:
Specifically the answer by Cameron MacFarland is exactly what I do. A service provided via an interfaceto provide IO and/or user interaction is the way to go here, for the following reasons:
具体来说,Cameron MacFarland 的回答正是我所做的。通过接口提供的服务来提供 IO 和/或用户交互是这里的方式,原因如下:
- It is testable
- It abstracts away the implementation of any dialogsso that your strategy for handling these types of things can be changed without affecting constituent code
- Does not rely on any communication patterns. A lot of suggestions you see out there rely on a mediator, like the Event Aggregator. These solutions rely on implementing two-way communication with partners on the other side of the mediator, which is both hard to implement and a very loose contract.
- ViewModels remain autonomous. I, like you, don't feel right given communication between the controller and the ViewModel. The ViewModel should remain autonomous if for no other reason that this eases testability.
- 它是可测试的
- 它抽象出任何对话框的实现,以便您可以更改处理这些类型事物的策略,而不会影响组成代码
- 不依赖任何通信模式。您在那里看到的许多建议都依赖于中介,例如事件聚合器。这些解决方案依赖于与中介另一端的合作伙伴实现双向通信,这既难以实施,又是一个非常松散的合约。
- ViewModels 保持自治。我和你一样,觉得控制器和 ViewModel 之间的通信不对。如果没有其他原因可以简化可测试性,ViewModel 应该保持自治。
Hope this helps.
希望这可以帮助。
回答by blindmeis
回答by Guge
I have come across similar problems. Here is how I have solved them, and why I have done what I have done.
我遇到过类似的问题。以下是我解决它们的方法,以及为什么我做了我所做的。
My solution:
我的解决方案:
My MainWindowViewModel has a property of type ModalViewModelBase called Modal. If my code needs a certain view to be modal, it puts a reference to it in this property. The MainWindowView watches this property through the INotifyPropertyChanged mechanism. If Modal is set to some VM, the MainWindowView class will take the VM and put it in a ModalView window where the appropriate UserControl will be shown through the magic of DataTemplates, the window is shown using ShowDialog. ModalViewModelBase has a property for DialogResult and a property called IsFinished. When IsFinished is set to true by the modal VM, the view closes.
我的 MainWindowViewModel 有一个名为 Modal 的 ModalViewModelBase 类型的属性。如果我的代码需要一个特定的视图是模态的,它会在这个属性中放置一个对它的引用。MainWindowView 通过 INotifyPropertyChanged 机制监视此属性。如果将 Modal 设置为某个 VM,则 MainWindowView 类将获取该 VM 并将其放入 ModalView 窗口中,在该窗口中将通过 DataTemplates 的魔法显示适当的 UserControl,该窗口使用 ShowDialog 显示。ModalViewModelBase 有一个 DialogResult 属性和一个名为 IsFinished 的属性。当模式 VM 将 IsFinished 设置为 true 时,视图将关闭。
I also have some special tricks for doing interactive things like this from backgroundworker threads that want to ask the user for input.
我还有一些特殊的技巧可以从想要询问用户输入的后台工作线程中执行这样的交互操作。
My reasoning:
我的推理:
The principle of modal views is that other views are disabled, while the modal is shown. This is a part of the logic of the View that is essentially lookless. That's why I have a property for it in the MainWindowViewModel. It I were to take it further, I should make every other property or command for all other VM's in the Main VM throw exceptions, while in modal mode, but I feel this to be excessive.
模态视图的原理是禁用其他视图,同时显示模态。这是 View 逻辑的一部分,本质上是无外观的。这就是为什么我在 MainWindowViewModel 中有一个属性。如果我更进一步,我应该让主 VM 中所有其他 VM 的所有其他属性或命令在模式模式下抛出异常,但我觉得这太过分了。
The View mechanism of actually denying the user any other actions, does not have to be performed with a popup window and showdialog, it could be that you put the modal view in the existing window, but disable all others, or some other thing. This view-related logic belongs in the view itself. (That a typical designer can't code for this logic, seems a secondary concern. We all need help some times.)
实际上拒绝用户任何其他操作的视图机制,不必使用弹出窗口和显示对话框来执行,可能是您将模态视图放在现有窗口中,但禁用所有其他操作或其他内容。这个与视图相关的逻辑属于视图本身。(典型的设计师无法为这种逻辑编码,这似乎是次要的问题。有时我们都需要帮助。)
So that's how I have done it. I offer it only as a suggestion, there is probably other ways of thinking about it, and I hope you get more replies too.
所以我就是这样做的。我提供的只是一个建议,可能还有其他的思考方式,也希望你能得到更多的回复。
回答by Raj
I've used EventAggregatorfrom Prism v2 in similar scenarios. Good thing about prims is that, you don't have to use entire framework in your MVVM application. You can extract EventAggregator functionality and use it along with your current setup.
我在类似的场景中使用过Prism v2 的EventAggregator。prims 的好处在于,您不必在 MVVM 应用程序中使用整个框架。您可以提取 EventAggregator 功能并将其与当前设置一起使用。
回答by xdoo
You might have a look at this MVVM article. It describes how a controller can communicate with the ViewModel:
您可能会查看这篇 MVVM 文章。它描述了控制器如何与 ViewModel 通信:
http://waf.codeplex.com/wikipage?title=Model-View-ViewModel%20Pattern&ProjectName=waf
http://waf.codeplex.com/wikipage?title=Model-View-ViewModel%20Pattern&ProjectName=waf