你是如何在MVVM中成功实现MessageBox.Show()功能的?

Edw*_*uay 41 wpf triggers messagebox mvvm

我有一个WPF应用程序,它在ViewModel中调用MessageBox.Show()方式(以检查用户是否真的要删除).这实际上是有效的,但是违背了MVVM,因为ViewModel不应该明确地确定View上发生了什么.

所以现在我在想如何在我的MVVM应用程序中最好地实现MessageBox.Show()功能,选项:

  1. 我可以收到一条短信,上面写着"你确定......?" 以及我的XAML中的边框中的两个按钮是和否全部,并在模板上创建一个触发器,使其基于名为AreYourSureDialogueBoxIsVisible的ViewModelProperty折叠/可见,然后当我需要此对话框时,将AreYourSureDialogueBoxIsVisible指定为"true" "还可以通过我的ViewModel中的DelegateCommand处理这两个按钮.

  2. 我也可以尝试用XAML中的触发器来处理这个问题,这样删除按钮实际上只会使一些Border元素出现,其中包含消息和按钮,而Yes按钮实际上是删除了.

对于曾经使用MessageBox.Show()的几行代码而言,这两种解决方案似乎都过于复杂.

您在哪些方面成功实现了MVVM应用程序中的Dialogue Box?

wek*_*mpf 12

救援服务.使用Onyx(免责声明,我是作者),这很简单:

public void Foo()
{
    IDisplayMessage dm = this.View.GetService<IDisplayMessage>();
    dm.Show("Hello, world!");
}
Run Code Online (Sandbox Code Playgroud)

在正在运行的应用程序中,这将间接调用MessageBox.Show("Hello,world!").在测试时,可以模拟IDisplayMessage服务并将其提供给ViewModel,以便在测试期间完成您想要完成的任务.

  • 大多数情况下从来都不是,但我只是不同意。这里没有紧密耦合,所以我会挑战某人来说明*为什么*这里存在设计问题。上面例子中的反模式是使用服务定位器而不是依赖注入。无论如何,IDisplayMessage 概念,这里的真正答案,不依赖于服务定位器或间接访问视图。 (2认同)

Aar*_*man 5

在你提到的两个中,我更喜欢选项#2.页面上的"删除"按钮只显示"确认删除对话框"."确认删除对话框"实际上启动了删除.

你有没有看过Karl Shifflett的WPF业务幻灯片和演示?我知道他做的是这样的.我会试着记住哪里.

编辑:查看演示#11"MVVM中的数据验证"(EditContactItemsControlSelectionViewModel.DeleteCommand).Karl从ViewModal调用一个弹出窗口(What!?:-).我其实更喜欢你的想法.似乎更容易进行单元测试.


Gra*_*ton 5

我只是创建一个接口(IMessageDisplay 或类似的),它被注入到虚拟机中,并且它具有诸如 MessageBox(ShowMessage() 等)之类的方法。您可以使用标准消息框或更具体的 WPF 消息框(我在 Prajeesh 的CodePlex 上使用这个消息框)来实现这一点。

这样一切都是分开的并且可测试的。


Jum*_*zza 5

现在要扩展Dean Chalk的答案,因为他的链接是kaput:

在App.xaml.cs文件中,我们将确认对话框连接到视图模型。

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    var confirm = (Func<string, string, bool>)((msg, capt) => MessageBox.Show(msg, capt, MessageBoxButton.YesNo) == MessageBoxResult.Yes);
    var window = new MainWindowView();
    var viewModel = new MainWindowViewModel(confirm);
    window.DataContext = viewModel;
    ...
}
Run Code Online (Sandbox Code Playgroud)

在视图(MainWindowView.xaml)中,我们有一个按钮可以在ViewModel中调用命令

<Button Command="{Binding Path=DeleteCommand}" />
Run Code Online (Sandbox Code Playgroud)

视图模型(MainWindowViewModel.cs)使用委托命令显示“您确定吗?” 对话并执行操作。在此示例中,它SimpleCommand相似,但是任何ICommand实现都应该这样做。

private readonly Func<string, string, bool> _confirm;

//constructor
public MainWindowViewModel(Func<string, string, bool> confirm)
{
    _confirm = confirm;
    ...
}

#region Delete Command
private SimpleCommand _deleteCommand;
public ICommand DeleteCommand
{
    get { return _deleteCommand ?? (_deleteCommand = new SimpleCommand(ExecuteDeleteCommand, CanExecuteDeleteCommand)); }
}

public bool CanExecuteDeleteCommand()
{
    //put your logic here whether to allow deletes
    return true;
}

public void ExecuteDeleteCommand()
{
    bool doDelete =_confirm("Are you sure?", "Confirm Delete");
    if (doDelete)
    {
        //delete from database
        ...
    }
}
#endregion
Run Code Online (Sandbox Code Playgroud)