Today, in this article, I will explain the multi binding in MVVM, which means if you want to pass the multiple command parameter in MVVM then how to pass it. First, you all are aware of Explain INotifyPropertyChanged In WPF - MVVM and ICommand Interface In MVVM - WPF.
To understand the multi binding, we will take an example, so we create an WPF Application, which contains two text boxes, which contain an integer value and one button. When the user clicks on the button, it will give you the sum. Both these numbers are from the textboxes and the output is displayed in the third textbox. Here, we can say that here on the button command, we have to pass two command parameters number1 and number2, so we have to use multi binding.
Code - MainWindow.xaml
<Window x:Class="MVVM_MultiBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewmodel="clr-namespace:MVVM_MultiBinding.ViewModel"
xmlns:converter="clr-namespace:MVVM_MultiBinding.Converter"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<viewmodel:ViewModel x:Key="vm"></viewmodel:ViewModel>
<converter:MyValueConverter x:Key="cv"></converter:MyValueConverter>
</Window.Resources>
<Grid Width="400" Height="200" DataContext="{Binding Source={StaticResource vm}}">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Number - 1 : " HorizontalContentAlignment="Right"></Label>
<TextBox Grid.Row="0" Grid.Column="1" Name="txtNumb1" Margin="5" Text="{Binding Path=Number1}"></TextBox>
<Label Grid.Row="1" Grid.Column="0" Content="Number - 2 : " HorizontalContentAlignment="Right"></Label>
<TextBox Grid.Row="1" Grid.Column="1" Name="txtNumb2" Margin="5" Text="{Binding Path=Number2}"></TextBox>
<Button Grid.Row="2" Grid.Column="1" Margin="5" Content="SUM" Command="{Binding Path=MyCommand}">
</Button>
<Label Grid.Row="3" Grid.Column="0" Content="Sum : " HorizontalContentAlignment="Right"></Label>
<TextBox Grid.Row="3" Grid.Column="1" Margin="5" Text="{Binding Path=NumberSum, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
</Grid>
</Window>
Here, in the example, mentioned above, we take one RelayCommand Class, which you already know, if you are not aware of this then read ICommand Interface In MVVM - WPF.
Code - RealyCommand.sc
public class RelayCommand:ICommand
{
Action<object> _execute;
Func<object, bool> _canexecute;
public RelayCommand(Action<object> execute,Func<object,bool> canexecute)
{
_execute = execute;
_canexecute = canexecute;
}
public bool CanExecute(object parameter)
{
if (_canexecute != null)
{
return _canexecute(parameter);
}
else
{
return false;
}
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
Now, we want one view model, which contains ‘Number1’,’Number2’ and ‘NumberSum’ property. It stores the value and it binds to the respective text box. Also, this view mode implements INotifyPropertyChanged interface, as we learnt in Explain INotifyPropertyChanged In WPF - MVVM article.
Code - Viewmodel.cs
public class ViewModel : INotifyPropertyChanged
{
public ICommand MyCommand { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged( string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
private int _number1;
public int Number1
{
get { return _number1; }
set { _number1 = value; OnPropertyChanged("Number1"); }
}
private int _number2;
public int Number2
{
get { return _number2; }
set { _number2 = value; OnPropertyChanged("Number2"); }
}
private int nubersum;
public int NumberSum
{
get { return nubersum; }
set { nubersum = value; OnPropertyChanged("NumberSum"); }
}
public ViewModel()
{
MyCommand = new MVVM_MultiBinding.RelayCommand.RelayCommand(execute, canexecute);
}
private bool canexecute(object parameter)
{
if (Number1 !=null || Number2 != null)
{
return true;
}
else { return false; }
}
private void execute(object parameter)
{
}
}
If you want to use multi binding, you have to use the Multi value converter interface, so we create a converter class and implement it with IMultiValueConvetr interface.
Code - MyValueConverter.cs
public class MyValueConverter:IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return values.Clone();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
Now, we give this viewmodel and Myconverter class as a referance to the view(UI). It also defines the Window resources property and assigns a unique key to it, in addition to setting the data context property of the parent control, as we discussed in the previous articles Explain INotifyPropertyChanged In WPF - MVVM and ICommand Interface In MVVM - WPF.
Now, we come to our main part like button control. Here, when the user clicks on the button, we have to pass two command parameters, which are given below.
<Button Grid.Row="2" Grid.Column="1" Margin="5" Content="SUM" Command="{Binding Path=MyCommand}">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource cv }">
<Binding ElementName="txtNumb1" Path="Text"/>
<Binding ElementName="txtNumb2" Path="Text"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
As shown in the code, given above, we define Button.Command Parameter tag. In this tag, we define the Multi binding tags and pass the converter source with them. Subsequently, we pass our parameter in Binding tag. We pass the element name and path for the command parameter. Please keep in mind here in whatever sequence you pass in the parameter, you will get this in the same sequence on the view model side.
Move to the view model side and go to execute the method here. We receive the parameter object, so we convert it to the object array. Subsequently, from the array, we get both the parameters by passing an array index. Additionally, we convert it to the integer, make sum of them and assign it to ‘NumberSum’.
private void execute(object parameter)
{
var values = (object[])parameter;
int num1 = Convert.ToInt32((string)values[0]);
int num2 = Convert.ToInt32((string)values[1]);
NumberSum = num1+num2;
}
Now, run the Application and check the result.