"你确定吗?" 提示.部分ViewModel还是纯粹的视图?

Gaz*_*yer 37 c# wpf mvvm

我一直在玩弄哪里放"你确定吗?" 在我的MVVM WPF应用程序中输入提示.

我倾向于认为这些纯粹是View的一部分.如果ViewModel公开了一个DeleteCommand,那么我希望该命令立即删除.

要将这些提示集成到ViewModel中,它必须公开一个单独RequestDeleteCommandDeletePromptItem属性来绑定提示,并且还可以兼作显示提示的触发器.

即使这样,也没有什么能阻止单元测试DeleteCommand直接调用,除非我在ViewModel中放置特定的逻辑来要求DeletePromptItem匹配作为参数提供的项目DeleteCommand.

但是,这对我来说只是看起来像ViewModel中的噪音.提示更像是一个用户界面问题,以防止错误点击等.对我来说,这表明它应该在视图中,确认提示调用DeleteCommand.

有什么想法吗?

Jon*_*Jon 16

提示应该肯定不会视图模型的一部分,但这并不一定意味着最好的解决方案是硬编码他们在查看(尽管这是一个非常合理的第一种方法).

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

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

编辑:我应该补充一点,我已经在原型项目中探索了使用Prism 4和交互请求,我对结果非常满意(有了一些框架代码,你甚至可以指定在特定的交互请求中完全发生的事情) XAML!).


Bol*_*ock 8

但是,这对我来说只是看起来像ViewModel中的噪音.提示更像是一个用户界面问题,以防止错误点击等.对我来说,这表明它应该在视图中,确认提示调用DeleteCommand.

我同意; 这样的提示应该在视图中处理,因为最终视图是用户看到和交互的内容,而不是视图模型.一旦您的视图获得了用户确认DeleteCommand应该调用的信息,请继续并在视图模型中调用它.

我看待它的方式,单元测试与用户交互并没有任何关系,除非你正在测试视图本身.


Dan*_*rth 6

在我看来,提示用户包括两部分:

  1. 确定是否应显示提示以及应对结果执行的操作的逻辑
  2. 实际显示提示的代码

第2部分显然不属于ViewModel.
但第1部分确实属于那里.

为了实现这种分离,我使用了ViewModel可以使用的服务,我可以为其提供特定于我所处环境的实现(WPF,Silverlight,WP7).

这导致代码如下:

interface IMessageBoxManager
{
    MessageBoxResult ShowMessageBox(string text, string title,
                                    MessageBoxButtons buttons);
}

class MyViewModel
{
    IMessageBoxManager _messageBoxManager;

    // ...

    public void Close()
    {
        if(HasUnsavedChanges)
        {
            var result = _messageBoxManager.ShowMessageBox(
                             "Unsaved changes, save them before close?", 
                             "Confirmation", MessageBoxButtons.YesNoCancel);
            if(result == MessageBoxResult.Yes)
                Save();
            else if(result == MessageBoxResult.Cancel)
                return; // <- Don't close window
            else if(result == MessageBoxResult.No)
                RevertUnsavedChanges();
        }

        TryClose(); // <- Infrastructure method from Caliburn Micro
    }
}
Run Code Online (Sandbox Code Playgroud)

这种方法不仅可以用来显示消息框,还可以显示其他窗口,如本答案中所述.

  • 我不确定这是否会引起关注.您现在在ViewModel中有一个硬编码的消息框提示.如果视图想要以其他方式进行确认,例如拖放,甚至是类型化响应,该怎么办?ViewModel应该对这些东西一无所知. (2认同)