4

我正在使用几个绑定到使用 CanExecute 委托初始化的 RelayCommands 的按钮。

RelayCommand DeleteCommand;
bool CanDelete()
{
    return BoolProp1 && BoolProp2;
}

...

DeleteCommand = new RelayCommand(Delete, CanDelete);

BoolProp1并且BoolProp2是 setter 正确 raise 的常规属性PropertyChanged,但众所周知,这不足以让 SL 重新评估CanExecute命令。这就是为什么我也叫Delete.RaiseCanExecuteChanged()两个二传手。

所有这些都可以正常工作(按钮被禁用和正确启用)直到某个时候,所有这些都停止了。那时,调用Delete.RaiseCanExecuteChanged()不再触发我的断点CanDelete(),按钮永远保持原样。

我花了 2 个小时试图找出没有效果的确切原因。我怀疑RaiseCanExecuteChanged()在单个“绑定迭代”期间多次调用会以某种方式破坏机制。

有什么提示吗?我已经在考虑使用通过...IsExecutable刷新的附加字段INotifyPropertyChanged

更新

RelayCommand实际上GalaSoft.MvvmLight.Command.RelayCommand来自MVVM Light Toolkit。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);
    }
}

对传递给构造函数的值设置一次_canExecuteFunc<bool>

我仍在努力尽量减少重现该问题。

更新

看我的回答。

4

2 回答 2

8

PEBKAC。我的框架在某些情况下运行代码

DeleteCommand = new RelayCommand(Delete, CanDelete);

不止一次,覆盖实际上绑定到新实例查看的命令。

如果有人遇到这个问题 - 请确保您调用RelayCommand.RaiseCanExecuteChanged()的是视图绑定到的同一个实例。

于 2011-08-03T22:01:32.743 回答
0

对于面临同样问题并且接受的答案对我没有帮助的其他人(为了我自己的记录,因为我今天花了几个小时来处理它)。

如果您在 VSTO 加载项中使用 MVVM Light,请确保 Office 应用程序有机会处理自己的消息以使其正常工作。例如,在我的例子中,我的 Ribbon 按钮监听CanExecuteChanged了底层 VM 的命令对象,无论我做什么都不会触发。花了几个小时后,我意识到我必须让 Office 应用程序喘口气并处理传入的消息,以便CanExecuteChanged被加载项捕获。RaiseCanExecuteChanged然后我所做的就是将我的函数移交DispatcherHelper给让它异步触发。直到那时,我的功能区按钮才开始对CanExecuteChanged事件做出反应。像这样的东西:

DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
  doc.Activate();
  ResetVariablesCommand.RaiseCanExecuteChanged();
});
于 2021-10-11T15:14:02.290 回答