MVVM 设计:在 ViewModel 中阻塞 MessageBox

MVVM design: Blocking MessageBox in ViewModel

本题涉及基于PRISM 5.0和MVVM模式的WPF应用程序。

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

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

问题是: 如果我在 ViewModel 中调用 MessageBox,ViewModel 从外部变为 untestable

//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;}

    }
}

一种可能性是,在调用 public 方法

的不同私有方法中提出问题
//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 中的用户?你能给我一个提示或link,PRISM 5.0 最好的是什么?

我知道,根据经验,不要在 ViewModel 中使用任何 UI 元素,但我认为除了阻塞 MessageBox 或其他东西之外别无选择,它会在继续之前阻塞进程。

谢谢任何提示!

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

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

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

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

Notification Request

Confirmation Request

Custom Content

Custom Request