ICommand - RelayCommand的CanExecute方法无法更新按钮的IsEnabled属性

3

我在viewModel中有以下的RelayCommand实现:

RelayCommand _resetCounter;

private void ResetCounterExecute()
{
    _data.ResetCounter();
}

private bool CanResetCounterExecute()
{
    if (_data.Counter > 0)
    {
        return true;
    }
    else
    {
        return false;
    }

}

public ICommand ResetCounter
{ 
    get 
    {

        if (_resetCounter == null)
        {
            _resetCounter = new RelayCommand(this.ResetCounterExecute,this.CanResetCounterExecute);
        }
        return _resetCounter; 
    }
}

通过在ResetCounterExecute方法中调用_data.ResetCounter();,我在我的模型中将计数器值重置为0。
这是我所使用的基于样例的RealyCommand类的实现。
internal class RelayCommand : ICommand
{
    readonly Action _execute;
    readonly Func<bool> _canExecute;

    public RelayCommand(Action execute)
        : this(execute, null)
    {
    }

    public RelayCommand(Action execute, Func<bool> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    [DebuggerStepThrough]
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute();
    }

    public event EventHandler CanExecuteChanged
    {
        add
        {
            if (_canExecute != null)
                CommandManager.RequerySuggested += value;
        }
        remove
        {
            if (_canExecute != null)
                CommandManager.RequerySuggested -= value;
        }
    }

    public void Execute(object parameter)
    {
        _execute();
    }
}

在XAML中,我将命令绑定到一个按钮:

<Button Name="btnResetCount" Content="Reset" Command="{Binding Path=CounterViewModel.ResetCounter}" Click="btnResetCount_Click">

我的问题是,只有在我点击UI中的任何控件后,按钮才会被启用。但我需要的是,只要应用_data.Counter > 0,按钮就会被启用。从我的研究来看,似乎我需要实现CommandManager.InvalidateRequerySuggested();或使用RelayCommand.RaiseCanExecuteChanged()。我想知道这两种方法是否是通知UI刷新绑定的唯一方法。另外,我还想问,在当前情况下如何实现RelayCommand.RaiseCanExecuteChanged()。我应该在哪里和如何引发它,以确保UI更改按钮状态(如果满足条件)。谢谢。
1个回答

2

当使用 CommandManager.RequerySuggested 时,您可以通过调用 CommandManager.InvalidateRequerySuggested() 强制 CommandManager 调用 RequerySuggested 事件。

或者,您可以实现 RaiseCanExecuteChanged。这可能是触发相同事件的更可靠方法。

例如:

internal class RelayCommand : ICommand
{
    ...

    public event EventHandler CanExecuteChanged;

    public void RaiseCanExecuteChanged()
    {
        EventHandler handler = CanExecuteChanged;
        if (handler != null)
            handler(this, EventArgs.Empty);
    }

    ...
}

当您想要使无效或更改_data.Counter时,请调用

ResetCounter.RaiseCanExecuteChanged();

此外,您可能还想阅读CommandManager.RequerySuggested如何工作?


@pushraj:感谢你的提示。但我不明白如何将“RaiseCanExecuteChanged”实现到我的代码中。我应该在哪里添加嵌套类?怎么添加? - ck84vi
您可以在代码中使用答案中的代码替换CanExecuteChanged,它不是嵌套类,而是代表通用代码的类。 - pushpraj
不知道为什么我之前没搞明白。非常感谢,现在它完美地运行了! - ck84vi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接