Search code examples
wpfmvvm-lightcommandbindingcommandparametercanexecute

MVVM Light canExecute always false with RelayCommand<bool> not RelayCommand<object>


Do anyone know why being specific with the MVVM Light RelayCommand generic type would cause its canExecute to always resolve to false for the binding? In order to get the correct behavior I had to use an object and then convert it to the desired type.

NOTE: canExecute was simplified to a boolean for testing the block that does not work and is normally a property CanRequestEdit.

Does NOT work:

public ICommand RequestEditCommand {
  get {
    return new RelayCommand<bool>(commandParameter => { RaiseEventEditRequested(this, commandParameter); },
                                  commandParameter => { return true; });
  }
}

Works:

public ICommand RequestEditCommand {
  get {
    return new RelayCommand<object>(commandParameter => { RaiseEventEditRequested(this, Convert.ToBoolean(commandParameter)); },
                                    commandParameter => { return CanRequestEdit; });
  }
}

XAML:

<MenuItem Header="_Edit..." Command="{Binding RequestEditCommand}" CommandParameter="true"/>

Solution

  • Look at the code for RelayCommand<T>, specifically the line I marked with "!!!":

    public bool CanExecute(object parameter)
    {
        if (_canExecute == null)
        {
            return true;
        }
    
        if (_canExecute.IsStatic || _canExecute.IsAlive)
        {
            if (parameter == null
    #if NETFX_CORE
                && typeof(T).GetTypeInfo().IsValueType)
    #else
                && typeof(T).IsValueType)
    #endif
            {
                return _canExecute.Execute(default(T));
            }
    
            // !!!
            if (parameter == null || parameter is T)
            {
                return (_canExecute.Execute((T)parameter));
            }
        }
    
        return false;
    }
    

    The parameter you are passing to your command is the string "true", not the boolean true, so the condition will fail because parameter is not null and the is clause is false. In other words, if the value of the parameter doesn't match the type T of the command, then it returns false.

    If you really want to hard-code a boolean into your XAML (i.e. your sample isn't dummy code), then look to this question for ways to do so.