关于 c#:MVVM 设计:在 ViewModel 中阻塞 MessageBox

 2022-01-08 

MVVM design: Blocking MessageBox in ViewModel

这个问题是指一个基于 PRISM 5.0 和 MVVM 模式的 WPF 应用程序。

有时,当用户做出可能会产生不良后果或负面后果的决定时,通常会询问用户,他是否真的想继续前进。

例如:
一种常见的方式,就是用一个消息框询问用户,如果他真的要删除数据,删除后无法恢复。

问题是:
如果我在 ViewModel 内部调用 MessageBox,则 ViewModel 将无法从外部进行测试。

1
2
3
4
5
6
7
8
9
10
11
12
//BAD!
public class ViewModel
{
    public Boolean Delete()
    {
        //Blocking and therefore untestable in automatic UnitTests
        MsgBoxResult result = MsgBox.Show("Do you really want to delete?");

        if (result == yes) {//Do stuff that deletes data here;}

    }
}

一种可能性是,在调用公共方法的不同私有方法中提出问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//BETTER, BUT OK?
public class ViewModel
{
    private void OnDeleteAction
    {
        MsgBoxResult result = MsgBox.Show("Do you really want to delete?");
        if (result == yes) {Delete();}
    }

    public Boolean Delete()
    {
        //Testable from the outside again, because no blocking question

        //Do stuff that deletes data here
    }

我的问题:这是一种好方法还是有一种更优雅的方式来询问 ViewModel 中的用户?你能给我一个提示或链接,什么是最好的 PRISM 5.0?

我知道,经验法则是,不要在 ViewModel 中使用任何 UI 元素,但我认为除了阻塞 MessageBox 或其他会阻塞进程的其他东西之外,别无选择,然后再继续。

谢谢你的提示!


我知道有两种替代方法可以减少 View 和 ViewModel 之间的耦合:使用交互服务和触发交互请求。两者都在这里得到了很好的解释;你可能想看看。

总体思路是抽象异步交互是如何完成的,并使用更类似于基于事件的逻辑的东西,同时允许 ViewModel 表达它希望与用户交互作为操作的一部分;最终结果是您可以记录此交互并对其进行单元测试。


Prism Interactivity 是您的最佳选择。这允许您执行确认、通知并创建与 MVVM 模式配合良好的自定义对话框。我在 Prism 应用程序中成功使用了它们。

以下是一些指向 GitHub 上 Prism 存储库中某些代码的链接:

通知请求

确认请求

自定义内容

自定义请求