WPF命令绑定不更新按钮启用状态

时间:2017-01-11 13:37:56

标签: c# wpf

Simple RelayCommand定义如下:

  public class RelayCommand : IDelegateCommand
    {
        readonly Predicate<object> _canExecute;
        readonly Action<object> _execute;

        public RelayCommand(Predicate<object> canExecute, Action<object> execute)
            : this(canExecute, execute, true)
        {
        }

        public RelayCommand(Predicate<object> canExecute, Action<object> execute, bool isCommandAllowed)
        {
            _canExecute = canExecute;
            _execute = execute;
            IsAllowed = isCommandAllowed;
        }

        public void RaiseCanExecuteChanged()
        {
            CanExecuteChanged(this, EventArgs.Empty);
        }

        #region ICommand Members

        public virtual bool CanExecute(object parameter)
        {
            return _canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged = delegate { };

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

IDelegateCommand的定义如下:

public interface IDelegateCommand : ICommand
{
    void RaiseCanExecuteChanged();
}

如下所示绑定到WPF按钮:

<Button Command="{Binding StartSimulationCommand}" Content="Start Simulation"/>

Command的相应ViewModel用法如下:

   public class MainViewModel 
    {
          // missing irrelevant bits

          public ICommand StartSimulationCommand
                {
                    get { return new RelayCommand(arg => true, arg =>
                    {
                        var inputValidationResponse = ValidateInputs();
                        if (!string.IsNullOrEmpty(inputValidationResponse))
                        {
                            _logger.Error(inputValidationResponse);
                            return;
                        }

                        // this method opens a websocket and if that operation is 
                        // successful, property called IsWebSocketOpen is updated.
                        OpenWebSocketChannel();

                        // update command states
                        StopSimulationCommand.RaiseCanExecuteChanged();

                    });
                    }
                }


            public RelayCommand StopSimulationCommand
            {
                get { return new RelayCommand(arg => IsWebSocketOpened, arg => { CloseWebSocketChannel(); }); }
            }

                  private bool _isWebSocketOpened;
            public bool IsWebSocketOpened {
                get { return _isWebSocketOpened; }
                set { SetField(ref _isWebSocketOpened, value, "IsWebSocketOpened"); }
            }
}

当我调用StopSimulationCommand.RaiseCanExecuteChanged时,绑定到StopSimulationCommand的按钮的状态不会更改为启用,即使该命令的谓词现在返回true。

我错过了什么?

1 个答案:

答案 0 :(得分:2)

您正在StopSimulationCommand的setter中创建RelayCommand的新实例。您应该在视图模型类的构造函数中创建命令一次

public class MainViewModel : INotifyPropertyChanged
{
    public MainViewModel ()
    {
        StopSimulationCommand = new RelayCommand(arg => IsWebSocketOpened, arg => { CloseWebSocketChannel(); });
    }

    public RelayCommand StopSimulationCommand { get; private set; }
}