DarioSantarelli.Blog(this);

Archive for November, 2010

[WPF] Binding multiple command parameters using MultiBinding

Posted by dariosantarelli on November 7, 2010


In this post, I’d like to show how we can pass multiple values into an ICommand implementation by using the CommandParameter property of an input control. This is useful especially in MVVM architectures, so that the View can interact with the ViewModel in a clean way, facing the fact that the Execute method of the ICommand interface allows only a single object.
A solution is to use the MultiBinding class which allows us to define a collection of Binding objects attached to the target CommandParameter property of our input control. In a concrete example, let’s consider a simple search box with an OK button and a checkbox “ignore case”. The OK button is bound to a custom FindCommand defined in the ViewModel.
When the user clicks on the OK button, we want two parameters to be passed to the command: the string to be searched and the “ignorecase” option. How can we bind these two parameters to the Button’s CommandParameter?
Well, first we have to create a class to hold the parameters.

public class FindCommandParameters
{
  public string Text { get; set; }
  public bool IgnoreCase { get; set; }
}

After that, we have to create a class that implements the IMultiValueConverter interface. This simply converts our multiple parameters into the class that we have defined before.

public class FindCommandParametersConverter : IMultiValueConverter
{ 
  public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    FindCommandParameters parameters = new FindCommandParameters(); 
    foreach (var obj in values)
    { 
       if (obj is string) parameters.Text = (string)obj;                
       else if (obj is bool) parameters.IgnoreCase = (bool)obj;
    } 
    return parameters;
  }
  public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}

As you can see in the code above, we can iterate through the list of input values of the Convert method, checking their type, and then correctly assign the properties of the parameter class. Obviously you can implement different solutions (you always know the order of the parameters set in the XAML), but the most important thing at this point is that the return value of the Convert method is what will be passed as argument to the Execute method of our FindCommand.
To wire up the XAML to take advantage of this class, we have to include the <Button.CommandParameter> element.  This contains the <MultiBinding> element, which has the “Converter” attribute. In the code below, the converter type is added as a resource to the button to make this post easier to read, but convention usually dictates resources are added at the Window level to allow reuse and readability.
Under the MultiBinding.Bindings element, we add a <Binding> element for each parameter that we need to pass into the command.

<TextBox x:Name="txtFind" />
<CheckBox x:Name="chkFindIgnoreCase" Content="Ignore case" />
 <Button Command="{Binding FindCommand}" Content="OK">
  <Button.Resources>
    <ui:FindCommandParametersConverter x:Key="findCommandParametersConverter" />
  </Button.Resources>
  <Button.CommandParameter>
    <MultiBinding Converter="{StaticResource findCommandParametersConverter}">
      <MultiBinding.Bindings>
        <Binding ElementName="txtFind" Path="Text" />
        <Binding ElementName="chkFindIgnoreCase" Path="IsChecked" />
      </MultiBinding.Bindings>
    </MultiBinding>
  </Button.CommandParameter>
</Button>

The final step is to consume the FindCommandParameters object instance in our FindCommand’s CanExecute and Execute methods.

Posted in WPF | Tagged: , , | 1 Comment »