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

Tim*_*ann 8 c# wpf mvvm relaycommand icommand

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

public event EventHandler CanExecuteChanged
{
    add
    {
        CommandManager.RequerySuggested += value;
    }
    remove
    {
        CommandManager.RequerySuggested -= value;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Tse*_*eng 3

这是一个简单、快速和肮脏的实现,主要仅用于教程案例,这些案例不将教程与特定的 MVVM 框架联系起来,而是充当通用的 DIY MVVM 教程。

除了紧密耦合之外,这种方法还有其他几个缺点。

CommandManager.InvalidateRequerySuggested()调用该方法时,CanExecute每个命令的方法都会被调用。如果您的应用程序中有数百个命令,这可能会对 WPF 应用程序的性能产生严重影响。

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

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

这个实现是否违反了 MVVM 模式?

从技术上来说是的。

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

并非如此,尽管您可以使用外部工厂来抽象它,但它似乎没有意义(请参阅上面的问题)

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

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