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

Is the common implementation of RelayCommand violating the MVVM pattern?

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

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

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

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

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

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

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

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

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

Is this implementation violating the MVVM pattern?

技术上是的。

Or do you maybe place the RelayCommand in your view somehow?

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

If this is indeed flawed, is there a best practice implementation that solves this issue?

无论如何都没有命令状态的全局失效。自己将需要执行状态的命令绑定在一起。