简体   繁体   English

RelayCommand RaiseCanExecuteChanged() 失败

[英]RelayCommand RaiseCanExecuteChanged() fails

I am using a couple of Buttons bound to RelayCommands initialized with CanExecute delegates.我正在使用几个绑定到用 CanExecute 委托初始化的 RelayCommand 的按钮。

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

...

DeleteCommand = new RelayCommand(Delete, CanDelete);

BoolProp1 and BoolProp2 are regular properties with setters correctly raising PropertyChanged , but as we all know, this is not enough to make SL reevaluate CanExecute on commands. BoolProp1BoolProp2是设置器正确引发PropertyChanged的常规属性,但众所周知,这不足以让 SL 在命令上重新评估CanExecute That's why i also call Delete.RaiseCanExecuteChanged() in both setters.这就是为什么我也在两个设置器中调用Delete.RaiseCanExecuteChanged()的原因。

All this works fine (buttons are disabled and enabled properly) up to some point, where is all stops.所有这些工作正常(按钮被禁用和正确启用)到某个点,所有停止的地方。 At that point, calling Delete.RaiseCanExecuteChanged() no longer fires my breakpoints in CanDelete() and buttons forever stay the way they were.那时,调用Delete.RaiseCanExecuteChanged()不再触发我在CanDelete()中的断点,并且按钮永远保持原样。

I spend 2 hours trying to isolate the exact cause with no effect.我花了 2 个小时试图找出确切的原因,但没有效果。 I suspect multiple RaiseCanExecuteChanged() calls during single "binding iteration" somehow break the mechanism.我怀疑在单个“绑定迭代”期间多次调用RaiseCanExecuteChanged()以某种方式破坏了该机制。

Any hints?有什么提示吗? I'm already considering using an additional IsExecutable field refreshed through INotifyPropertyChanged ...我已经在考虑使用通过INotifyPropertyChanged刷新的附加IsExecutable字段 ...

UPDATE更新

RelayCommand is actually GalaSoft.MvvmLight.Command.RelayCommand from MVVM Light Toolkit . RelayCommand实际上是来自MVVM Light ToolkitGalaSoft.MvvmLight.Command.RelayCommand ILSpy shows a pretty trivial implementation of ICommand: 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);
    }
}

with _canExecute being a Func<bool> set once to the value passed to constructor. _canExecute是一个Func<bool>设置一次传递给构造函数的值。

I am still working to minimally reproduce the issue.我仍在努力以最低限度地重现该问题。

UPDATE更新

See my answer.看我的回答。

PEBKAC. PEBKAC。 My framework in certain cases ran the code 在某些情况下我的框架运行代码

DeleteCommand = new RelayCommand(Delete, CanDelete);

more then once, overwriting commands that were actually bound to view with new instances. 多一次,覆盖实际绑定到新实例查看的命令。

If somebody has this problem - make sure you're calling RelayCommand.RaiseCanExecuteChanged() on the same instance that the view is bound to. 如果有人遇到此问题 - 请确保在视图绑定的同一实例上调用RelayCommand.RaiseCanExecuteChanged()

For anyone else who faced the same issue and the accepted answer didn't help me (and for my own record, as I spent a few hours today with it).对于遇到同样问题并且接受的答案对我没有帮助的任何其他人(以及我自己的记录,因为我今天花了几个小时)。

If you're using MVVM Light in a VSTO add-in, make sure that the Office application gets a chance to process its own messages to get this to work.如果您在 VSTO 加载项中使用 MVVM Light,请确保 Office 应用程序有机会处理自己的消息以使其正常工作。 For example, in my case I had my Ribbon buttons listening to CanExecuteChanged of underlying VM's command objects, which would not fire no matter what I did.例如,在我的例子中,我的功能区按钮侦听底层 VM 命令对象的CanExecuteChanged ,无论我做什么都不会触发。 After spending a few hours, I realized that I had to let Office application take a breath and process incoming message to allow CanExecuteChanged to be caught by the add-in.花了几个小时后,我意识到我必须让 Office 应用程序喘口气并处理传入的消息,以允许加载项捕获CanExecuteChanged What I then did was to hand over my RaiseCanExecuteChanged function to DispatcherHelper to let it fire asynchronously.然后我所做的是将我的RaiseCanExecuteChanged function 交给DispatcherHelper让它异步触发。 It was only then that my Ribbon buttons started reacting to CanExecuteChanged events.直到那时我的功能区按钮才开始对CanExecuteChanged事件做出反应。 Something like this:是这样的:

DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
  doc.Activate();
  ResetVariablesCommand.RaiseCanExecuteChanged();
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM