我得到了一个 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/

10-16 04:20