我得到了一个 WPF 应用程序 ,它显示了一个绑定(bind)到命令的按钮,如下所示:
<Button Command="{Binding Path=TestrunStartCommand}" Content="GO!">
该命令定义如下:
public ICommand TestrunStartCommand
{
get { return new RelayCommand(TestrunStartExecute, () => !IsTestrunInProgress); }
}
public bool IsTestrunInProgress
{
get{
return _isTestrunInProgress;
}
set{
_isTestrunInProgress = value;
RaisePropertyChanged(IsTestrunInProgressPropertyName);
}
}
问题是,在我将
IsTestrunInProgress
设置为 false 后,该按钮不会立即启用,而是在我在应用程序窗口内单击后才启用。你能帮我理解这种行为并告诉我如何解决这个问题吗?
进一步阅读:
wpf command pattern - when does it query canexecute
最佳答案
ICommand
接口(interface)暴露了一个事件 ICommand.CanExecuteChanged
,用于通知 UI 何时重新确定命令驱动的 UI 组件的 IsEnabled
状态。
根据您使用的 RelayCommand
的实现,您可能需要引发此事件;许多实现公开了一个方法,例如 RelayCommand.RaiseCanExecuteChanged()
,您可以调用它来强制刷新 UI。RelayCommand
的一些实现使用 CommandManager.RequerySuggested
,在这种情况下,您需要调用 CommandManager.InvalidateRequerySuggested()
来强制刷新 UI。
长话短说,您需要从属性 setter 中调用这些方法之一。
更新
由于在事件焦点发生变化时确定按钮的状态,因此我相信正在使用 CommandManager
。因此,在您的属性(property)的 setter 中,在分配支持字段后,调用 CommandManager.InvalidateRequerySuggested()
。
更新 2 RelayCommand
实现来自 MVVM light 工具包。当从 WPF/.NET 使用时,实现包装了从 CommandManager
公开的方法和事件。这意味着这些命令在大多数情况下(UI 更改或焦点元素更改)会自动运行。但是在少数情况下,例如这种情况,您将需要手动强制命令重新查询。使用此库执行此操作的正确方法是在 RaiseCanExecuteChanged()
上调用 RelayCommand
方法。
关于c# - PropertyChanged 后 ICommand CanExecute 不触发?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14479303/