考虑引用Josh Smith' article WPF Apps With The Model-View-ViewModel Design Pattern,特别是RelayCommand
的示例实现(在图3中)。 (对于这个问题,无需通读整篇文章。)
总的来说,我认为实现非常出色,但是我对将CanExecuteChanged
订阅委派给CommandManager
的RequerySuggested
事件有疑问。 documentation for RequerySuggested
指出:
但是RelayCommand
的示例实现并未对订阅的处理程序进行任何维护:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
RelayCommand
的客户端,要求RelayCommand
的用户了解CanExecuteChanged
的实现并自己维护实时引用? RelayCommand
的实现修改为类似于以下内容以减轻CanExecuteChanged
订户的潜在过早GC是否有意义:// This event never actually fires. It's purely lifetime mgm't.
private event EventHandler canExecChangedRef;
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
this.canExecChangedRef += value;
}
remove
{
this.canExecChangedRef -= value;
CommandManager.RequerySuggested -= value;
}
}
最佳答案
我也相信此实现是有缺陷的,因为它肯定会将弱引用泄漏给事件处理程序。这实际上是非常糟糕的事情。
我正在使用MVVM Light工具箱和在其中实现的RelayCommand
,它的实现方式与本文中相同。
以下代码将永远不会调用OnCanExecuteEditChanged
:
private static void OnCommandEditChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var @this = d as MyViewBase;
if (@this == null)
{
return;
}
var oldCommand = e.OldValue as ICommand;
if (oldCommand != null)
{
oldCommand.CanExecuteChanged -= @this.OnCanExecuteEditChanged;
}
var newCommand = e.NewValue as ICommand;
if (newCommand != null)
{
newCommand.CanExecuteChanged += @this.OnCanExecuteEditChanged;
}
}
但是,如果我这样更改它,它将起作用:
private static EventHandler _eventHandler;
private static void OnCommandEditChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var @this = d as MyViewBase;
if (@this == null)
{
return;
}
if (_eventHandler == null)
_eventHandler = new EventHandler(@this.OnCanExecuteEditChanged);
var oldCommand = e.OldValue as ICommand;
if (oldCommand != null)
{
oldCommand.CanExecuteChanged -= _eventHandler;
}
var newCommand = e.NewValue as ICommand;
if (newCommand != null)
{
newCommand.CanExecuteChanged += _eventHandler;
}
}
唯一的区别?就像
CommandManager.RequerySuggested
文档中指出的那样,我将事件处理程序保存在一个字段中。关于wpf - 乔什·史密斯(Josh Smith)对RelayCommand的实现是否有缺陷?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2281566/