使用 MVVM 从 WPF 应用程序启动对话框/子窗口的标准方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17308945/
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
Standard Approach of Launching Dialogs/Child Windows from a WPF Application using MVVM
提问by MoonKnight
All, I would like to know the recognised best approach/industry standard of launching [child] dialogs/windows from an WPF using the MVVM pattern. I have come across the following articles:
所有,我想知道使用 MVVM 模式从 WPF 启动 [子] 对话框/窗口的公认最佳方法/行业标准。我遇到了以下文章:
A. CodeProject - Showing Dialogs When Using the MVVM Pattern
A. CodeProject - 使用 MVVM 模式时显示对话框
This approach seems good but excessive to me. The is some degree of code replication and I am not convinced this is the right way to go.
这种方法看起来不错,但对我来说太过分了。这是某种程度的代码复制,我不相信这是正确的方法。
B. WPF MVVM and Showing Dialogs
This briefly runs through three options with various links which are all fairly/very poor at explaining the methodology or are of-topic.
这简要介绍了具有各种链接的三个选项,这些选项在解释方法或主题方面都相当/非常差。
Can someone please provide an explanation of the industry standardmethod/approach of launching dialogs from a WPF application using MVVM and preferably some links to further reading material? If you can provide an example yourself I would of course be most appreciative!
有人可以解释一下使用 MVVM 从 WPF 应用程序启动对话框的行业标准方法/方法,最好是一些进一步阅读材料的链接吗?如果您能自己提供一个例子,我当然会非常感激!
Thanks for your time.
谢谢你的时间。
采纳答案by Ibrahim Najjar
First of all, i don't know of any "industry-standard" way for showing dialogs using MVVM because there is no such thing.
Secondly, Welcome to MVVM, you have just touched on of the areas that MVVM don't have a standard for.
To tell you the truth, MVVM has many pain points and this is the reason why there are tons of MVVM frameworks out there, just to mention a few MVVM Light, PRISM, Caliburn.Micro, Cinch, Catel, WAF, Baboon, shell i stop or you want more.
Now to answer your question and after dealing with most of those frameworks, i noticed one commonality, they all use a DI/IoC container and then provide you with an interface, something like IDialogManager and an implementation of their own, and then they ask you to accept this interface in your view model and use it to show dialogs. So to sum this up, i would use dependency injection, have an interface for showing dialogs, and then provide and implementation of that, and register it with the di container and then consume it from my view model or views.
Edit:So you have picked PRISM (which in my opinion)is hardest between them all in showing dialogs. Now that's aside, there is the hard way which is by using Interaction Requests(check the middle of the article), or you can use this Answeras a quicker way.
首先,我不知道使用 MVVM 显示对话框的任何“行业标准”方式,因为没有这样的东西。
其次,欢迎使用 MVVM,您刚刚触及了 MVVM 没有标准的领域。
说实话,MVVM 有很多痛点,这就是为什么有大量 MVVM 框架的原因,仅举几个 MVVM Light、PRISM、Caliburn.Micro、Cinch、Catel、WAF、Baboon、shell i停止或者你想要更多。
现在回答你的问题,在处理了大多数框架之后,我注意到一个共同点,它们都使用一个 DI/IoC 容器,然后为你提供一个接口,比如 IDialogManager 和他们自己的实现,然后他们问你在你的视图模型中接受这个接口并用它来显示对话框。所以总结一下,我会使用依赖注入,有一个用于显示对话框的界面,然后提供和实现它,并将它注册到 di 容器,然后从我的视图模型或视图中使用它。
编辑:所以你选择了 PRISM (在我看来)在显示对话框中是最难的。撇开这些,还有一个困难的方法是使用交互请求(检查文章的中间),或者您可以使用此答案作为更快的方法。
回答by Wojciech Kulik
Recently, I've implemented my own Navigation Service for WPF, which uses Caliburn.Micro's WindowManager (but you could replace it by something else).
最近,我为 WPF 实现了自己的导航服务,它使用 Caliburn.Micro 的 WindowManager(但您可以用其他东西替换它)。
Example (how to use):
示例(如何使用):
_navigationService.GetWindow<ClientDetailsViewModel>()
.WithParam(vm => vm.IsEditing, true)
.WithParam(vm => vm.Client, SelectedClient)
.DoIfSuccess(() => RefreshSelectedClient())
.ShowWindowModal();
Implementation:
执行:
namespace ClientApplication.Utilities
{
public class NavigationService : INavigationService
{
SimpleContainer _container;
IWindowManager _windowManager;
public NavigationService(SimpleContainer container, IWindowManager windowManager)
{
_container = container;
_windowManager = windowManager;
}
public INavigationService<TViewModel> GetWindow<TViewModel>()
{
return new NavigationService<TViewModel>(_windowManager, (TViewModel)_container.GetInstance(typeof(TViewModel), null));
}
}
public class NavigationService<TVM> : INavigationService<TVM>
{
IWindowManager _windowManager;
TVM _viewModel;
System.Action _action;
public NavigationService(IWindowManager windowManager, TVM viewModel)
{
_windowManager = windowManager;
_viewModel = viewModel;
}
public INavigationService<TVM> WithParam<TProperty>(Expression<Func<TVM, TProperty>> property, TProperty value)
{
var prop = (PropertyInfo)((MemberExpression)property.Body).Member;
prop.SetValue(_viewModel, value, null);
return this;
}
public INavigationService<TVM> DoBeforeShow(Action<TVM> action)
{
action(_viewModel);
return this;
}
public INavigationService<TVM> DoIfSuccess(System.Action action)
{
_action = action;
return this;
}
public void ShowWindow(IDictionary<string, object> settings = null)
{
_windowManager.ShowWindow(_viewModel, null, settings);
}
public bool ShowWindowModal(IDictionary<string, object> settings = null)
{
bool result = _windowManager.ShowDialog(_viewModel, null, settings) ?? false;
if (result && _action != null)
_action();
return result;
}
}
}
Interfaces:
接口:
namespace Common
{
public interface INavigationService<TVM>
{
INavigationService<TVM> WithParam<TProperty>(Expression<Func<TVM, TProperty>> property, TProperty value);
INavigationService<TVM> DoIfSuccess(System.Action action);
INavigationService<TVM> DoBeforeShow(Action<TVM> action);
void ShowWindow(IDictionary<string, object> settings = null);
bool ShowWindowModal(IDictionary<string, object> settings = null);
}
public interface INavigationService
{
INavigationService<TViewModel> GetWindow<TViewModel>();
}
}
回答by Gayot Fow
The most recent release of Prism (download here) contains a so-called "Reference Implementation" of an MVVM application called "Stock Trader". My rationale was that if the Prism team is calling it a "Reference Implementation", that's the most "standard" from their point of view (if anything in MVVM is standard), and the logical choice to press on with.
Prism 的最新版本(在此处下载)包含一个名为“Stock Trader”的 MVVM 应用程序的所谓“参考实现”。我的理由是,如果 Prism 团队称其为“参考实现”,那么从他们的角度来看,这是最“标准”的(如果 MVVM 中的任何内容都是标准的),也是继续推进的合乎逻辑的选择。
The source contains an infrastructure library for raising modal dialogs, and it's pretty good. So I adopted that library and have deployed it successfully (I uploaded such an app to Codeplex).
源代码包含一个用于提高模态对话框的基础架构库,它非常好。所以我采用了该库并成功部署了它(我将这样的应用程序上传到 Codeplex)。
I needed to tweak the code to 1add the parent's icon to the title bar because the library didn't provide for it; and [2] add some meaningful text to the title bar because the library left it blank and [3] add a delegate to invoke when the dialog closes. It's abstracted to the extent that a VM can raise a dialog by passing two strings (i.e., the Unity Registration Names) to a mediator. Those changes are available on Codeplex.
我需要将代码调整为1将父图标添加到标题栏,因为库没有提供它;[2] 向标题栏添加一些有意义的文本,因为库将其留空,并且 [3] 添加一个委托以在对话框关闭时调用。它被抽象到 VM 可以通过将两个字符串(即 Unity 注册名称)传递给中介来引发对话的程度。这些更改在 Codeplex 上可用。
So among all the other 'standards' the "Reference Implementation" should minimally participate as a viable choice. The more oblique answer to your question is that if your View Models are sufficiently isolated and work entirely through POCO interfaces, then in THEORY, it shouldn't matter because switching to another 'standard' should be a trivial exercise.
因此,在所有其他“标准”中,“参考实施”应该作为可行的选择最低限度地参与。对您的问题的更间接的回答是,如果您的视图模型充分隔离并且完全通过 POCO 接口工作,那么在理论中,这应该无关紧要,因为切换到另一个“标准”应该是一项微不足道的练习。
回答by blindmeis
回答by flup
Creating a dialog service has worked out well for me, and is also suggested in both your links.
创建对话服务对我来说效果很好,并且在您的两个链接中也提出了建议。
Later I saw the same solution at the dev days in an MVVM presentation by Gill Cleeren. Check the link for working code samples (though written for Metro)
后来我在Gill Cleeren 的 MVVM 演示文稿中在开发日看到了相同的解决方案。检查工作代码示例的链接(虽然是为 Metro 编写的)
Only thing that nags me a bit about the dialog service is that it is in some way UI technology (rich client) dependent.
关于对话服务,唯一让我烦恼的是它在某种程度上依赖于 UI 技术(富客户端)。
A simple request-response web frontend View can be built on top of the same ViewModel and Model code that the WPF XAML binds to. Until the ViewModel starts popping up dialogs through the dialog service. I would not know how to implement the dialog service for a web view. Implementing dialogs there would require pushing a bit more logic to the view.
一个简单的请求-响应 Web 前端视图可以构建在 WPF XAML 绑定到的相同 ViewModel 和模型代码之上。直到 ViewModel 开始通过对话框服务弹出对话框。我不知道如何为 Web 视图实现对话服务。在那里实现对话框需要向视图推送更多逻辑。
回答by Bill Zhang
Purpose of using interface to implement dialogs is to make code testable. In this case, "A" is widely used, but it is still hard to say "Standard". If you do not have test on your ViewModel or you can test your ViewModel avoid touching dialogs, such as using Extract-Override, you can definitely do not follow the instruction.
使用接口实现对话框的目的是使代码可测试。在这种情况下,“A”被广泛使用,但仍然很难说“标准”。如果您没有对您的 ViewModel 进行测试,或者您可以测试您的 ViewModel 避免触摸对话框,例如使用 Extract-Override,您绝对可以不按照说明进行操作。

