按钮保持禁用状态 - DelegateCommand不重新评估CanExecute处理程序

时间:2016-08-13 09:47:54

标签: wpf mvvm binding

问题:按钮永远不会启用。

<Button Name="btnCompareAxises"Command="{Binding CompareCommand}"
          Content="{Binding VM.CompareAxisButtonLabel}" 
        IsEnabled="{Binding VM.IsCompareButtonEnabled}">
</Button>

ViewModel构造函数:

 this.CompareCommand = new DelegateCommand(CompareCommand, ValidateCompareCommand);

问题似乎与按钮的已注册命令的CanExecute事件处理程序有关。 加载应用程序时,CanExecute处理程序返回false。 这很好,因为最初没有满足条件。

canExecute处理程序仅在应用程序启动时或单击按钮时运行。您无法单击禁用的按钮,因此如果从CanExecute处理程序返回的初始值为false,则该按钮将永远保持禁用状态!

问题:
是否必须再次启用该按钮,仅使用绑定到它的命令。 有点像,嘿命令请重新评估是否符合此按钮的条件?

为什么将IsEnabled属性置于Coercion部分下而不是本地部分?

enter image description here

命令:

public class DelegateCommand : ICommand
{
    private readonly Func<object, bool> canExecute;
    private readonly Action<object> execute;

    public DelegateCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        this.execute = execute;
        this.canExecute = canExecute;
    }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return this.canExecute == null || this.canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        this.execute(parameter);
    }

    public void RaiseCanExecuteChanged()
    {
        this.OnCanExecuteChanged();
    }

    protected virtual void OnCanExecuteChanged()
    {
        var handler = this.CanExecuteChanged;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

解决:

我必须调整DelegateCommand类才能使它工作:

我已将CommandManager.RequerySuggested添加到公开CanExecuteChanged事件属性。

现在,当UI中的soemthing发生变化时,它会自动重新评估命令的CanExecute方法!

public class DelegateCommand : ICommand
{
    private readonly Func<object, bool> canExecute;
    private readonly Action<object> execute;

    public DelegateCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        this.execute = execute;
        this.canExecute = canExecute;
    }

    /// CommandManager
    /// Go to the "References" part of your class library and select "Add Reference". 
    /// Look for an assembly called "PresentationCore" and add it.
    public event EventHandler CanExecuteChanged
    {
        add
        {
            _internalCanExecuteChanged += value;
          CommandManager.RequerySuggested += value;

        }
        remove
        {
            _internalCanExecuteChanged -= value;
            CommandManager.RequerySuggested -= value;
        }
    }

    event EventHandler _internalCanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return this.canExecute == null || this.canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        this.execute(parameter);
    }

    public void RaiseCanExecuteChanged()
    {
        this.OnCanExecuteChanged();
    }

    protected virtual void OnCanExecuteChanged()
    {
        var handler = this._internalCanExecuteChanged;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}

从按钮中删除了这个:

 IsEnabled="{Binding VM.IsCompareButtonEnabled}"

此处的绑定不是必需的,因为CanExecute处理程序将处理按钮的启用/禁用状态!