Wpf 从ViewModel到视图的通知

Wpf 从ViewModel到视图的通知,wpf,mvvm,Wpf,Mvvm,我需要在MVVM WPF应用程序中从ViewModel向View发送通知。在大多数情况下,它将是视图侧的简单MessageBox。在ViewModel中使用System.Windows.MessageBoxResult或System.Windows.MessageBoxImage等类型是否违反MVVM模式是不可接受的(在这种情况下,VM必须引用特定于UI的库) 我需要从VM传递标题、消息和通知类型,通过创建自定义枚举,我实际上是在从.NET Framework复制现有功能。您可以让视图实现一个接

我需要在MVVM WPF应用程序中从ViewModel向View发送通知。在大多数情况下,它将是视图侧的简单MessageBox。在ViewModel中使用System.Windows.MessageBoxResult或System.Windows.MessageBoxImage等类型是否违反MVVM模式是不可接受的(在这种情况下,VM必须引用特定于UI的库)


我需要从VM传递标题、消息和通知类型,通过创建自定义枚举,我实际上是在从.NET Framework复制现有功能。

您可以让视图实现一个接口,比如说
INotificationService
,然后将视图传递给视图模型构造函数。这不会违反MVVM,并且您仍然可以使用视图上的
DataContext
属性将视图模型绑定到视图。

我决定尽可能保持视图模型中没有UI(视图)内容,因此,我将以MessageBox为灵感创建自定义枚举,并完全根据我的需要进行定制。

您不需要通知机制。这是一个选择。另一种是使用简单服务类:

public class ViewModel
{
    IDialogService _dialogService; //ctor injection or use service locator

    public void CommandExecute()
    {
        _dialogService.ShowMessageBox(...);
    }
}

public interface IDialogService
{
    bool? ShowMessageBox(params....);
}

public class DialogService : IDialogService
{
    public bool? ShowDialog(params...)
    {
        MessageBox.Show(params...);
    }
}
我发现这种方法更直接、更容易理解和调试。消息传递可能很容易变成内存泄漏,在这种情况下,我看不到我的方法有任何好处

编辑:

您是在ShowMessageBox参数中使用自定义枚举,还是使用 System.Windows.MessageBoxImage

首先,视图模型属于表示层。可以在ViewModel中使用枚举,如
System.Windows.MessageBoxImage
。 在MVVM中,视图模型与视图分离的原因如下:

  • ViewModels以易于从视图中使用的方式从模型中公开数据和逻辑(例如数据绑定)
  • ViewModels更易于测试
  • ViewModels提供了更好的设计时支持(可混合性、测试数据)
  • ViewModels将应用程序逻辑与实际的表示标记分离,这使其更易于理解(可读性)
使用类似于
System.Windows.MessageBoxImage
的枚举是否会破坏上述任何一点?答案是否定的


如果希望在多个平台(例如WPF、UWP和Xamarin)上重用IDialogService和ViewModels,则需要创建自己的枚举,因为它可能不存在于所有平台上。黄金法则是:如果不需要,不要添加另一层抽象。

“使用System.Windows.MessageBoxResult或System.Windows.MessageBoxImage等类型是否违反MVVM模式是不可接受的?”这只取决于您打算如何重用视图模型。通过使用这些类型,重用仅限于WPF应用程序。否则就没什么问题了。但当然也有不同意见的人。我认为ViewModel应该与这些MessageBox枚举之类的纯视图内容100%分离,不管它是什么类型的应用程序。那你为什么要问这个问题?你的理论只是一种意见,我通过在ViewModel中引发事件并在View中捕获它来完成这些通知。方法绑定到视图的DataContextChanged事件中的VM事件。按照您的方式,视图必须知道视图模型中有一个它应该侦听的事件。而我向你们描述的方式将使它在关注点分离方面更加明确,因为视图和虚拟机都不知道关于另一个的任何信息;视图不必知道任何关于视图模型的信息,视图模型也不必知道任何关于INotificationService依赖性的信息,除了它实现了一些名为Notify的方法或其他方法。我读了很多关于MVVM的书,如果视图知道ViewModel,那就完全可以了。只有ViewModel不了解视图,而Model不了解ViewModel。无论如何,我需要在ViewModel中拒绝/确认使用纯UI枚举。@TimothyGhanem视图可以很好地了解ViewModel。但您是对的,所需的对话框应该使用显式接口进行请求。我只对一些可选的单向信息使用事件方法,视图可以自由决定是否值得显示。@grek40我使用这种方法是双向的。例如,ViewModel需要确认某些内容,因此它会引发事件。无论什么将响应此事件,ViewModel都会在引发后从自定义的EventArgs获取值,并基于此执行操作。我无法想象如何使用一些界面来做同样的事情,它只会使事情复杂化,并且不会比我的解决方案带来任何好处。谢谢。我很清楚我可以从VM中显示一些东西的所有选项。但我的问题是,我不确定在VM中使用UI(视图)类型是否正确。查看您的IDialogService.ShowMessageBox。将有哪些参数?您需要显示信息或警告。您是在ShowMessageBox参数中使用自定义枚举,还是使用System.Windows.MessageBoxImage?如果要使用MessageBoxImage,则需要在使用IDialogService.ShowMessageBox的每个位置(项目)引用System.Windows UI库。