2
votes

The following two elements are firing in my implementation of ICommand differently and causing problems. When the implementation enters CanExecuteChanged(object parameter) for the TextBox, the value of parameter is null. When it enters the same method for the Button, the value of parameter is equal to the CommandParameter.

Ideally I'd like in both cases that the CommandParameter value is not sent to the CanExecuteChanged, only to Execute.

Implementation of ICommand

public event EventHandler CanExecuteChanged
        {
            add
            {
                canExecuteChanged += value;
                CommandManager.RequerySuggested += value;
            }
            remove
            {
                canExecuteChanged -= value;
                CommandManager.RequerySuggested -= value;
            }
        }


        public bool CanExecute(object parameter)
        {
            if (parameter is bool)
            {
                this.canExecute = (bool)parameter;
            }

            return this.canExecute;
        }

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


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


        private void OnCanExecuteChanged()
        {
            if (this.canExecuteChanged != null)
            {
                this.canExecuteChanged(this, EventArgs.Empty);
            }
        }

TextBox

<TextBox Width="80" Margin="2,2,2,2" Text="{Binding LastName, UpdateSourceTrigger=PropertyChanged}" MaxLength="25">
                <TextBox.InputBindings>
                    <KeyBinding Key="Enter" Command="{Binding SearchCommand}">
                        <KeyBinding.CommandParameter>
                            <s:Boolean>True</s:Boolean>
                        </KeyBinding.CommandParameter>
                    </KeyBinding>
                </TextBox.InputBindings>
            </TextBox>

Button

<Button Margin="2,2,2,2" Padding="10,0,10,0" Content="Search">
                <Button.InputBindings>
                    <MouseBinding Command="{Binding SearchCommand }" MouseAction="LeftClick">
                        <MouseBinding.CommandParameter>
                            <s:Boolean>True</s:Boolean>
                        </MouseBinding.CommandParameter>
                    </MouseBinding>
                </Button.InputBindings>
            </Button>
1

1 Answers

0
votes

In this case, try the implementation ICommand of @JoshSmith, for me both options worked well:

RelayCommand

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

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

    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
        {
            throw new ArgumentNullException("execute");
        }

        _execute = execute;
        _canExecute = canExecute;
    }

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

    public event EventHandler CanExecuteChanged
    {
        add
        {
            CommandManager.RequerySuggested += value;
        }

        remove
        {
            CommandManager.RequerySuggested -= value;
        }
    }

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

SearchCommand

private RelayCommand _searchCommand = null;

public ICommand SearchCommand
{
    get
    {
        if (_searchCommand == null)
        {
            _searchCommand = new RelayCommand(param => this.Search(param), param => true);
        }

        return _searchCommand;
    }
}

private void Search(object param)
{
    bool parameter = (bool)param;

    if (parameter) 
    {
        MessageBox.Show("Pressed the Enter Key");
    }
}