【发布时间】:2011-10-19 11:48:06
【问题描述】:
我正在使用几个绑定到 RelayCommands 的按钮,这些 RelayCommands 由 CanExecute 委托初始化。
RelayCommand DeleteCommand;
bool CanDelete()
{
return BoolProp1 && BoolProp2;
}
...
DeleteCommand = new RelayCommand(Delete, CanDelete);
BoolProp1 和 BoolProp2 是常规属性,setter 正确地提升了PropertyChanged,但众所周知,这不足以让 SL 在命令上重新评估 CanExecute。这就是为什么我在两个 setter 中都调用 Delete.RaiseCanExecuteChanged()。
直到某个时候,所有这些都可以正常工作(按钮被禁用和启用),所有这些都停止了。那时,调用Delete.RaiseCanExecuteChanged() 不再触发我在CanDelete() 中的断点,并且按钮将永远保持原样。
我花了 2 个小时试图找出确切的原因,但没有任何效果。我怀疑在单个“绑定迭代”期间多次调用 RaiseCanExecuteChanged() 会以某种方式破坏机制。
有什么提示吗?我已经在考虑使用通过INotifyPropertyChanged 刷新的额外IsExecutable 字段...
更新
RelayCommand 实际上是来自MVVM Light Toolkit 的GalaSoft.MvvmLight.Command.RelayCommand。 ILSpy 展示了一个非常简单的 ICommand 实现:
public bool CanExecute(object parameter)
{
return this._canExecute == null || this._canExecute.Invoke();
}
public void RaiseCanExecuteChanged()
{
EventHandler canExecuteChanged = this.CanExecuteChanged;
if (canExecuteChanged != null)
{
canExecuteChanged.Invoke(this, EventArgs.Empty);
}
}
_canExecute 是 Func<bool> 设置一次为传递给构造函数的值。
我仍在努力尽量减少重现该问题。
更新
看我的回答。
【问题讨论】:
-
发布更多代码。什么是 RelayCommandEx?命令实现是什么样的?如果可能,创建一个非常简单的复制并发布完整的代码。
-
RelayCommandEx是我处理此问题的失败尝试(尝试缓存 CanExecute() 值,如果不需要则不触发 CanExecuteChanged)。 -
我有一个模糊的记忆,它与某些事情有关(我认为在我的情况下它是 WPF 按钮)没有缓存 EventHandler 和弱引用。当我有时间时会尝试弄清楚它是什么,但可能会帮助你走上正确的道路。您可能希望为 CanExecuteChanged 事件实现添加/删除访问器,然后在 remove 中设置断点以查看它何时被删除。
-
看我的回答。谢谢你的时间。
标签: c# silverlight mvvm mvvm-light relaycommand