Search code examples
c#wpfmvvmmultibindingrelaycommand

WPF Multibinding - Need to use Relaycommand


So, I have an element which has a command with 2 parameters to pass.

I previously did this with a snippet of code I found, but cannot for the life of me remember how to do it or find it again.

So, here is the multivalueconverter I previously created:

public class MultiValueConverter : IMultiValueConverter
{

    public object Convert(object[] values, Type targetType,
    object parameter, CultureInfo culture)
    {
        return values.Clone();
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        return (value as string).Split(' ');
    }

}

Now, I need to just assign the function I want to call in the ICommand. I normally use a line similar to:

enemyPopupTooltip = new RelayCommand(param => this.EnemyPopupTooltipEx(param),null);

However, this wont work when its multivalue.How can I use my relaycommand to pass 2 parameters, using the multivalueconverter, into my function?

For reference, here is everything inside relaycommand class:

public class RelayCommand : ICommand
{
    /// <summary>
    /// Initializes a new instance of the <see cref="RelayCommand"/> class.
    /// </summary>
    /// <param name="execute">The execute.</param>
    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="RelayCommand"/> class.
    /// </summary>
    /// <param name="execute">The execute.</param>
    /// <param name="canExecute">The can execute.</param>
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }

    /// <summary>
    /// Defines the method that determines whether the command can execute in its current state.
    /// </summary>
    /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
    /// <returns>
    /// true if this command can be executed; otherwise, false.
    /// </returns>
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    /// <summary>
    /// Occurs when changes occur that affect whether or not the command should execute.
    /// </summary>
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    /// <summary>
    /// Defines the method to be called when the command is invoked.
    /// </summary>
    /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    /// <summary>
    /// Action
    /// </summary>
    private readonly Action<object> _execute;


    /// <summary>
    /// Predicate
    /// </summary>
    private readonly Predicate<object> _canExecute;

Solution

  • you said:

    However, this wont work when its multivalue

    This assumption is wrong. It does work!

    When your multiconverter returns array of values, then this array is passed as a parameter to Command.Execute method.

    new RelayCommand(EnemyPopupTooltipEx, null);
    
    public void EnemyPopupTooltipEx(object parameter){
       var values = (object[])parameters;
    }
    

    however, this is very dirty approach. I guess you are passing some UIElement(s) to the command parameter. This is violation of viewmodel's responsibility. Consider moving code that need reference to UIElement to codebehind.