如何实现 `ICommand.CanExecuteChanged`?该问题涉及 IT 技术。

5

背景

在阅读Josh Smith的有关CommandGroup的文章时,我注意到互联网上有很多关于如何实现ICommand.CanExecuteChanged的评论。

类似的问题在StackOverflow上这里发布过,但是:

  1. 我觉得没有明确的答案,
  2. 在评论中没有足够的空间来添加额外的上下文。

供参考:

  1. Josh Smith关于CommandGroup的原始文章使用了一个简单的.NET事件
  2. Josh Smith的RelayCommand使用了CommandManager 实现CanExecuteChanged
  3. 微软自家的RoutedCommand使用了CommandManager 实现CanExecuteChanged
  4. 微软自家PRISM库(版本:6)也使用了一个简单的.NET事件(之前的版本使用了弱引用)

我的问题

我相对较新于WPF,并且想知道在Josh Smith的CommandGroup中如何实现CanExecuteChanged事件,以避免任何意外行为或内存泄漏?

额外阅读

Josh Smith: 使用CommandGroup聚合WPF命令

Josh Smith: 使用MVVM设计模式的WPF应用程序

StackOverflow: Josh Smith的RelayCommand实现是否有缺陷?

StackOverflow: 有关CanExecuteChanged的评论

Microsoft: RoutedCommand

PRISM 6:DelegateCommandBase

1个回答

1
假设您将一个命令绑定到一个按钮上。当按钮即将呈现时,它会调用CanExecute()方法,并根据结果呈现为启用或禁用状态。 WPF会自动在“决定”的时候调用CanExecute()方法,但您不应该依赖这种行为。
因此,当您实现ICommand时,请声明一个名为UpdateCommand()的方法,在您决定时引发相应的事件。 例如,如果单击按钮会启动一个缓慢的操作,并且应在上一个操作完成后再次触发,则应该引发两次事件 - 一次是在开始操作之前,另一次是在操作完成后。
没有所谓的“最佳的ICommand.CanExecuteChanged实现方式”。可能这就是不在框架中提供默认ICommand实现的原因之一。 大多数MVVM框架都提供了默认实现:RelayCommand、ActionCommand、ParameterCommand、AsyncCommand等。 它们使事情变得更加简单 - 只需传递一个委托即可开始工作。 Josh Smith的文章解决了不同的问题,即在XAML中链接多个路由命令的巧妙方法。
总的来说:
  1. 在MVVM中使用ICommand
  2. 当您创建可重复使用的控件并希望命令向上传递到视觉树时,请使用RoutedCommand,以便感兴趣的祖先可以处理它
  3. 您可以使用装饰器设计模式并装饰您所有的命令,以便添加一个上层功能,例如仅供特权用户使用的命令,一次性禁用所有命令等。只需确保装饰器订阅了实际命令的CanExecuteChanged事件,并代表其重新引发该事件。

谢谢您的反馈。我明白您的意思,但这似乎并不是那么简单明了。以Josh Smith的RelayCommand实现是否有缺陷?为例。这个帖子包括了一些非常有经验的开发人员的评论,他们在这个问题上来回讨论。您有什么想法? - Pressacco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接