CheckBox Binding In MVVM - WPF

Today, I will explain how to use checkbox in WPF using MVVM pattern. Before starting this article please read Explain INotifyPropertyChanged In WPF - MVVM and ICommand Interface In MVVM - WPF article.

Let’s take an example to create one WPF Application, put four checkboxes and put one text box in it. The user has to select the check box and whatever check box the user selects, you have to display the list of all the checked checkboxes in the text box.

Thus, we create a WPF Window, as shown below.

Code - MainWindow.xaml

<Window x:Class="MVVM_Checkbox.View.Window1"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        Title="Window1" Height="350" Width="525">  
    <StackPanel Orientation="Vertical" Margin="20" >  
        <CheckBox Width="120" Name="cbIndia" Content="India"></CheckBox>  
        <CheckBox Width="120" Name="cbUS" Content="US"></CheckBox>  
        <CheckBox Width="120" Name="cbUK" Content="UK"></CheckBox>  
        <CheckBox Width="120" Name="cbChina" Content="China"></CheckBox>  
        <TextBox Width="300" Margin="20"></TextBox>  
    </StackPanel>  
</Window>

Here, when the user checked the checkbox, we have to display its selected checkbox content in the textbox, so first we have to create a command for the checkbox, which is checked. In simple words, we have to create a checkbox, which is checked on the change of the event in Windows form Application, but in MVVM pattern, we say that we have to create a command for the same. Thus, we create the Relay Command class, which implements the ICommand interface. This is taught in the   ICommand Interface In MVVM - WPF article.

Code - RalayCommand.cs

public class RelayCommand:ICommand  
{  
    Action<object> _executemethod;  
    Func<object, bool> _canexecutemethod;  

    public RelayCommand(Action<object> executemethod,Func<object,bool> canexecutemethod)  
    {  
        _executemethod = executemethod;  
        _canexecutemethod = canexecutemethod;  
    }  

    public bool CanExecute(object parameter)  
    {  
        if (_executemethod != null)  
        {  
            return _canexecutemethod(parameter);  
        }else  
        {  
            return false;  
        }  
    }  

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

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

Now we have to make view-model class in which we have to define two properties.

String Name;  
ObservableCollection<String> Countries;  

Here ‘Name’ property is used to store the selected countries' names, as shown in the single string. When the user selects any country, we concat the checkbox name in this ‘Name’ property and when it is unchecked, we remove this name from the string. Finally, we bind this property ‘Name’ to the text box.

‘Countries’ property contains the one type of collection of the string. Here, we take the string as the country name. Based on checked and un-checked of check box, we add or remove the country name from the collection.

Now, we have to implement the INotifyPropertyChanged interface to update the UI, based on the change in view-model, which was discussed in Explain INotifyPropertyChanged In WPF - MVVM.

public class ViewModel:INotifyPropertyChanged  
{      
    private ObservableCollection<string> _countries;  
    public ObservableCollection<string> Countries  
    {  
        get { return _countries; ; }  
        set  
        {  
            _countries = value;  
            OnPropertyChange("Countries");  
        }  
    }  

    private string _name;  
    public string Name  
    {  
        get { return _name; }  
        set   
        {   
            _name = value;  
            OnPropertyChange("Name");  
        }  
    }     
    public event PropertyChangedEventHandler PropertyChanged;  

    private void OnPropertyChange(string propertyname)  
    {  
        if (PropertyChanged !=null)  
        {  
            PropertyChanged(this, new PropertyChangedEventArgs(propertyname));  
        }  
    }
} 

Now, we define the ICommand for the fire.

public ICommand MyCommand { get; set; }  

Also, we create two new methods - canexecute and execute, where canexecute allows to fire execute method or not. On the other hand, execute method contains the actual logic like assigning all the checked check box values to the ‘Name’ property.

When command fires from the view screen, we have to decide that, whether the user checks the check box or un-checks the check box. Base on its action we perform our further operation. In command parameters, we have to pass multiple (two) parameters, where one is check box content name and another is "IsChecked". Thus, we have to use Multi Binding. Multi Binding is already discussed in Explain Multi Binding In MVVM - WPF article.

private bool canexecutemethod(object parameter)  
{  
    return true;  
}  

private void executemethod(object parameter)  
{  
    var values = (object[])parameter;  
    string name = (string)values[0];  
    bool check = (bool)values[1];  
    if (check)  
    {  
        Countries.Add(name);  
    }  
    else  
    {  
        Countries.Remove(name);  
    }  
      
    Name = "";  
    foreach (string item in Countries)  
    {  
        Name = Name + item;  
    }  
}

Here, I will explain the function, given above. First, we receive the collection as a parameter collection, which contains two values, where one is checkbox content name and second is IsChecked property. Now, we separate string and Boolean variable.

Subsequently, we check is IsChecked is true then we need to add this checkbox content name to our collection and if it’s false, we remove it from our collection.

Finally, we take all the country names from the collection and store it in the single string, using for loop.

Now, we create the multi value converter, as we discussed in Explain Multi Binding In MVVM - WPF article, if you want to use multi binding , you have to use I value converter.

Code - MyConverter.cs

public class MyConverter: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, go to the view and give reference of the view-mode and converter to the view

xmlns:viewmodel="clr-namespace:MVVM_Checkbox.ViewModel"  
xmlns:converter="clr-namespace:MVVM_Checkbox.Converter"  

Create the Window resource property and assign the unique key to it.

<Window.Resources>  
   <viewmodel:ViewModel x:Key="vm"></viewmodel:ViewModel>  
   <converter:MyConverter x:Key="cv"></converter:MyConverter>  
</Window.Resources>  

Now, set the data context value for the parent control.

<StackPanel Orientation="Vertical" Margin="20" DataContext="{Binding Source={StaticResource vm}}">  

Now, we will assign the command property to the checkbox and then we set the command parameter to the checkbox. Here, we use multi binding. We disused it in previous article Explain Multi Binding In MVVM - WPF.

<CheckBox Width="120" Name="cbIndia" Content="India" Command="{Binding MyCommand}">  
    <CheckBox.CommandParameter>  
        <MultiBinding Converter="{StaticResource cv}">  
            <Binding ElementName="cbIndia" Path="Content"/>  
            <Binding ElementName="cbIndia" Path="IsChecked"/>  
        </MultiBinding>  
    </CheckBox.CommandParameter>  
</CheckBox> 

Now, we set the text property of the text box as ‘Name’.

<TextBox Width="300" Margin="20" Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>  

Code - MainWindow.xaml

<Window x:Class="MVVM_Checkbox.MainWindow"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        xmlns:viewmodel="clr-namespace:MVVM_Checkbox.ViewModel"  
        xmlns:converter="clr-namespace:MVVM_Checkbox.Converter"  
        Title="MainWindow" Height="350" Width="525">  
    <Window.Resources>  
        <viewmodel:ViewModel x:Key="vm"></viewmodel:ViewModel>  
        <converter:MyConverter x:Key="cv"></converter:MyConverter>  
    </Window.Resources>  
    <StackPanel Orientation="Vertical" Margin="20" DataContext="{Binding Source={StaticResource vm}}">  
        <CheckBox Width="120" Name="cbIndia" Content="India" Command="{Binding MyCommand}">  
            <CheckBox.CommandParameter>  
                <MultiBinding Converter="{StaticResource cv}">  
                    <Binding ElementName="cbIndia" Path="Content"/>  
                    <Binding ElementName="cbIndia" Path="IsChecked"/>  
                </MultiBinding>  
            </CheckBox.CommandParameter>  
        </CheckBox>  
        <CheckBox Width="120" Name="cbUS" Content="US" Command="{Binding MyCommand}">  
            <CheckBox.CommandParameter>  
                <MultiBinding Converter="{StaticResource cv}">  
                    <Binding ElementName="cbUS" Path="Content"/>  
                    <Binding ElementName="cbUS" Path="IsChecked"/>  
                </MultiBinding>  
            </CheckBox.CommandParameter>  
        </CheckBox>  
        <CheckBox Width="120" Name="cbUK" Content="UK" Command="{Binding MyCommand}">  
            <CheckBox.CommandParameter>  
                <MultiBinding Converter="{StaticResource cv}">  
                    <Binding ElementName="cbUK" Path="Content"/>  
                    <Binding ElementName="cbUK" Path="IsChecked"/>  
                </MultiBinding>  
            </CheckBox.CommandParameter>  
        </CheckBox>  
        <CheckBox Width="120" Name="cbChina" Content="China" Command="{Binding MyCommand}">  
            <CheckBox.CommandParameter>  
                <MultiBinding Converter="{StaticResource cv}">  
                    <Binding ElementName="cbChina" Path="Content"/>  
                    <Binding ElementName="cbChina" Path="IsChecked"/>  
                </MultiBinding>  
            </CheckBox.CommandParameter>  
        </CheckBox>  
        <TextBox Width="300" Margin="20" Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>  
    </StackPanel>  
</Window>

Now, run the Application and show the output.