RelayCommand的常见实现是否违反了MVVM模式?

时间:2016-03-10 08:04:02

标签: c# wpf mvvm icommand relaycommand

RelayCommand的一个非常常见的实现似乎包括以下几行:

public event EventHandler CanExecuteChanged
{
    add
    {
        CommandManager.RequerySuggested += value;
    }
    remove
    {
        CommandManager.RequerySuggested -= value;
    }
}

这对我来说似乎非常有缺陷,因为CommandManager是WPF组件,通常我的命令位于viewmodel类中。由于viewmodel不应该知道视图并且应该使用不同的框架等,这对我来说似乎很奇怪。例如,如果将viewmodel分离到一个不知道WPF名称空间(例如PCL)的额外项目中,则甚至不可能实现此实现。

此实现是否违反MVVM模式?
或者您可能会以某种方式将RelayCommand放在您的视图中? 如果这确实存在缺陷,是否有最佳实践解决方案可以解决这个问题?

1 个答案:

答案 0 :(得分:3)

这是一个简单快捷的方法。脏实现主要仅用于不将教程绑定到特定MVVM框架的教程案例,而是作为一个通用的自助MVVM教程。

这种方法 - 除紧耦合外 - 还有其他几个缺点。

调用CommandManager.InvalidateRequerySuggested()方法时,将调用每个命令的CanExecute方法。如果您的应用程序中有100个命令,则会对WPF应用程序的性能产生严重影响。

我个人总是建议使用成熟的MVVM框架(Prism是我最喜欢的LoB应用程序)。这些命令通常不以这种方式实现,但是您调用MyCommand.OnCanExecuteChanged()(在Prism的情况下)为一个命令触发CanExecute验证。

如果你有复合或多个相互依赖的命令,你可以自己在代码中绑定它,即在视图中存储相关命令列表并循环使用它或者注册它们的OnCanExecuteChanged()方法到多播委托并调用它。

  

此实现是否违反了MVVM模式?

技术上是的。

  

或者您是否可以以某种方式将RelayCommand放在您的视图中?

不是真的,虽然你可以用外部工厂来抽象它,但似乎没有意义(见上面的问题)

  

如果这确实存在缺陷,是否有解决此问题的最佳实践实施?

无论如何都不要对命令状态进行全局失效。自己绑定命令,需要将执行状态绑定在一起。