Bindable Check Box and Radio Button

In my previous post, Check Box in Xamarin Forms, we’ve discussed about how to create checkbox, or at least something that has effect like check box in Xamarin Forms. I created that post based on my previous project that only required me to make a simple and plain check box list. In my current project, the requirement has escalated. I need to create several list of check box and radio button, and they need to talk to each other. By talk to each other, I mean if the user do something to one of them, let say the radio button, it will be affect the check box, and/or vice versa.

It will be complicated for me if I just use the method that I’ve used in previous project. I need some  improvements.  So, I created custom class of check box and radio button with some bindable properties on it. That custom class enable me to re-use the check box and radio button anytime I want, and then their bindable properties make it easy for me to manipulate it from view model. I also, once again, utilize Flow List View in this project to simplify user interaction process. Now, let’s get started.

Custom Content View

The first step we gonna do is creating custom content view of the check box and radio button. The following code is the content view of the check box.
BindableCode1

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class BindableCheckBox : ContentView, INotifyPropertyChanged
{
    public BindableCheckBox()
    {
        InitializeComponent();
    }

    public static BindableProperty IconSourceProperty =
        BindableProperty.Create(nameof(IconSource), typeof(string), typeof(BindableCheckBox), null, BindingMode.TwoWay);

    public string IconSource
    {
        get => (string)GetValue(IconSourceProperty);
        set => SetValue(IconSourceProperty, value);
    }

    public static BindableProperty MenuTitleProperty =
        BindableProperty.Create(nameof(MenuTitle), typeof(string), typeof(BindableCheckBox), null, BindingMode.TwoWay);

    public string MenuTitle
    {
        get => (string)GetValue(MenuTitleProperty);
        set => SetValue(MenuTitleProperty, value);
    }

    public static BindableProperty TitleColorProperty =
         BindableProperty.Create(nameof(TitleColor), typeof(Color), typeof(BindableCheckBox), Color.Transparent, BindingMode.TwoWay);

    public Color TitleColor
    {
        get => (Color)GetValue(TitleColorProperty);
        set => SetValue(MenuTitleProperty, value);
   }
}

As you can see above, the class contains some properties that are bind to xaml file. And we will be bind that properties from view model later. And here’s the code of the custom radio button. It’s actually pretty similar.

BindableCode2

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class BindableRadioButton : ContentView, INotifyPropertyChanged
{
    public BindableRadioButton()
    {
        InitializeComponent();
    }

    public static BindableProperty IconSourceProperty =
        BindableProperty.Create(nameof(IconSource), typeof(string), typeof(BindableRadioButton), null, BindingMode.TwoWay);

    public string IconSource
    {
        get => (string)GetValue(IconSourceProperty);
        set => SetValue(IconSourceProperty, value);
    }

    public static BindableProperty MenuTitleProperty =
        BindableProperty.Create(nameof(MenuTitle), typeof(string), typeof(BindableRadioButton), null, BindingMode.TwoWay);

    public string MenuTitle
    {
        get => (string)GetValue(MenuTitleProperty);
        set => SetValue(MenuTitleProperty, value);
    }
}

View Model

Now, we move on to the second step. We need to create view model for each of them, the check box and radio button, to data bind their properties and notify if there is any change to it. The following codes are the example of the radio button and check box view model.

public class PickingColorViewModel : BaseViewModel
{
    protected ObservableCollection listRadioButton;
    public ObservableCollection ListRadioButton
    {
        get => listRadioButton;
        set => SetProperty(ref listRadioButton, value);
    }

    protected BindableRadioButtonViewModel selectedRadioButton;
    public BindableRadioButtonViewModel SelectedRadioButton
    {
        get => selectedRadioButton;
        set => SetProperty(ref selectedRadioButton, value);
    }

    public ICommand RadioButtonTappedCommand { get; set; }

    protected ObservableCollection listCheckBox;
    public ObservableCollection ListCheckBox
    {
        get => listCheckBox;
        set => SetProperty(ref listCheckBox, value);
    }

    protected BindableCheckBoxViewModel selectedCheckBox;
    public BindableCheckBoxViewModel SelectedCheckBox
    {
        get => selectedCheckBox;
        set => SetProperty(ref selectedCheckBox, value);
    }

    public ICommand CheckBoxTappedCommand { get; set; }

    public PickingColorViewModel()
    {
        ListRadioButton = new ObservableCollection()
        {
            new BindableRadioButtonViewModel(){ IsSelected = true, EnableProperty = true, MenuTitle = "Enable" },
            new BindableRadioButtonViewModel(){ IsSelected = false, EnableProperty = false, MenuTitle = "Disable" }
        };

        ListCheckBox = new ObservableCollection()
        {
            new BindableCheckBoxViewModel() { IsEnabled = true, IsChecked = false, MenuTitle ="Cyan", DefaultTitleColor = Color.Cyan },
            new BindableCheckBoxViewModel() { IsEnabled = true, IsChecked = false, MenuTitle ="Indigo", DefaultTitleColor = Color.Indigo },
            new BindableCheckBoxViewModel() { IsEnabled = true, IsChecked = false, MenuTitle ="Firebrick", DefaultTitleColor = Color.Firebrick },
        };

        RadioButtonTappedCommand = new Command(RadioButtonTapped);
        CheckBoxTappedCommand = new Command(CheckBoxTapped);
    }

    private void CheckBoxTapped()
    {
        foreach (BindableCheckBoxViewModel check in ListCheckBox)
        {
            if (check.MenuTitle == SelectedCheckBox.MenuTitle)
                check.IsChecked = !check.IsChecked;
        }
    }

    private void RadioButtonTapped()
    {
        foreach (BindableRadioButtonViewModel radio in ListRadioButton)
        {
            if (radio.MenuTitle == SelectedRadioButton.MenuTitle)
                radio.IsSelected = true;
            else
                radio.IsSelected = false;

        }

        foreach (BindableCheckBoxViewModel check in ListCheckBox)
        {
            check.SetEnable(SelectedRadioButton.EnableProperty);
        }
    }
}

From the view model codes above, you can see that we will manipulate the image, text color and inability of the check box. And for the radio button, we’ll only manipulate the image, but it also has EnableProperty that we’ll use to manipulate the inability of the check box. I use those properties just for example. If you want to bind other properties such as Background color or Text Size, all you have to do is just adding more properties to view model and custom content view. The name of property in view model and content view have to be same. Let say, your property in view model is MenuBackgroundColor, in content view it has to be MenuBackgroundColor as well, or it won’t be bind. Now. let’s see how we’ll use it.

Implementation

For example of using this bindable check box and radio button, I’ve created a simple app that has list of check box and radio button. Each check box will have different color and the radio button will determine the inability of the check box. And I will put each list in a flow list view and let it handle the user interaction. Here’s the xaml code looks like.

BindableCode3

Now, after we done with the xaml, we’ll create the view model that will manipulate the properties that already bind in xaml. Here’s the code of the view model.

public class PickingColorViewModel : BaseViewModel
{
    protected ObservableCollection listRadioButton;
    public ObservableCollection ListRadioButton
    {
        get => listRadioButton;
        set => SetProperty(ref listRadioButton, value);
     }

    protected BindableRadioButtonViewModel selectedRadioButton;
    public BindableRadioButtonViewModel SelectedRadioButton
    {
        get => selectedRadioButton;
        set => SetProperty(ref selectedRadioButton, value);
    }

    public ICommand RadioButtonTappedCommand { get; set; }

    protected ObservableCollection listCheckBox;
    public ObservableCollection ListCheckBox
    {
        get => listCheckBox;
        set => SetProperty(ref listCheckBox, value);
    }

    protected BindableCheckBoxViewModel selectedCheckBox;
    public BindableCheckBoxViewModel SelectedCheckBox
    {
        get => selectedCheckBox;
        set => SetProperty(ref selectedCheckBox, value);
    }

    public ICommand CheckBoxTappedCommand { get; set; }

    public PickingColorViewModel()
    {
       ListRadioButton = new ObservableCollection()
       {
             new BindableRadioButtonViewModel(){ IsSelected = true, EnableProperty = true, MenuTitle = "Enable" },
             new BindableRadioButtonViewModel(){ IsSelected = false, EnableProperty = false, MenuTitle = "Disable" }
       };

       ListCheckBox = new ObservableCollection()
       {
            new BindableCheckBoxViewModel() { IsEnabled = true, IsChecked = false, MenuTitle ="Cyan", DefaultTitleColor = Color.Cyan },
            new BindableCheckBoxViewModel() { IsEnabled = true, IsChecked = false, MenuTitle ="Indigo", DefaultTitleColor = Color.Indigo },
            new BindableCheckBoxViewModel() { IsEnabled = true, IsChecked = false, MenuTitle ="Firebrick", DefaultTitleColor = Color.Firebrick },
       };

       RadioButtonTappedCommand = new Command(RadioButtonTapped);
       CheckBoxTappedCommand = new Command(CheckBoxTapped);
    }

    private void CheckBoxTapped()
    {
        foreach(BindableCheckBoxViewModel check in ListCheckBox)
        {
            if (check.MenuTitle == SelectedCheckBox.MenuTitle)
                check.IsChecked = !check.IsChecked;
        }
    }

    private void RadioButtonTapped()
    {
        foreach(BindableRadioButtonViewModel radio in ListRadioButton)
        {
            if (radio.MenuTitle == SelectedRadioButton.MenuTitle)
                radio.IsSelected = true;
            else
                radio.IsSelected = false;
        }

        foreach(BindableCheckBoxViewModel check in ListCheckBox)
        {
            check.SetEnable(SelectedRadioButton.EnableProperty);
        }
    }
}

Credit:

  • Check Box Icon from FlatIcon, Checked Check Box icon by Google, Empty Check Box icon by Dave Gandy
  • Radio Button Icon from clker by Zorik
  • Flow List View by Daniel Luberda (github)

Sample Code is available in my Github repo

Advertisements

15 thoughts on “Bindable Check Box and Radio Button

      1. Thanks a lot Sir, m using your code but my flowlist is not displaying any data.. i want to bind radio button to it but its empty.. In BaseViewModel Class there is dependency service being used.. do we need to use interface to get it working??

        Like

      2. Yes Shrushtee, you need to install flowlistview nuget package and then refer it in xaml. Anyway now you can see the sample code in my github repo

        Like

  1. Sir, Can You please Check my where m doing mistake?
    Below is My code,

    public class BaseViewModel : INotifyPropertyChanged
    {

    bool isBusy = false;
    public bool IsBusy
    {
    get { return isBusy; }
    set { SetProperty(ref isBusy, value); }
    }

    string title = string.Empty;
    public string Title
    {
    get { return title; }
    set { SetProperty(ref title, value); }
    }

    protected bool SetProperty(ref T backingStore, T value,
    [CallerMemberName]string propertyName = “”,
    Action onChanged = null)
    {
    if (EqualityComparer.Default.Equals(backingStore, value))
    return false;

    backingStore = value;
    onChanged?.Invoke();
    OnPropertyChanged(propertyName);
    return true;
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = “”)
    {
    var changed = PropertyChanged;
    if (changed == null)
    return;

    changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
    }
    }

    public class PickingColorViewModel : BaseViewModel
    {
    private ObservableCollection listRadioButton = new ObservableCollection();
    public ObservableCollection ListRadioButton
    {
    get { return listRadioButton; }
    set { SetProperty(ref listRadioButton, value); }
    }

    public BindableRadioButtonViewModel selectedRadioButton;
    public BindableRadioButtonViewModel SelectedRadioButton
    {
    get => selectedRadioButton;
    set => SetProperty(ref selectedRadioButton, value);
    }

    public ICommand RadioButtonTappedCommand { get; set; }

    public string Name { get; set; }

    public PickingColorViewModel(){

    listRadioButton.Add(new BindableRadioButtonViewModel() { IsSelected = true, MenuTitle =”Poor” , IconSource = “radioborder.png” });
    listRadioButton.Add(new BindableRadioButtonViewModel() {IsSelected = false, MenuTitle = “Average”, IconSource = “radioborder.png” });
    listRadioButton.Add(new BindableRadioButtonViewModel() {IsSelected = false, MenuTitle = “Good”, IconSource = “radioborder.png” });
    listRadioButton.Add(new BindableRadioButtonViewModel() { IsSelected = false, MenuTitle = “Execellent”, IconSource = “radioborder.png” });

    RadioButtonTappedCommand = new Command(RadioButtonTapped);
    }

    public void RadioButtonTapped()
    {
    foreach (BindableRadioButtonViewModel radio in ListRadioButton)
    {
    if (radio.MenuTitle == SelectedRadioButton.MenuTitle)
    radio.IsSelected = true;
    else
    radio.IsSelected = false;
    }

    }
    }

    public class BindableRadioButtonViewModel : BaseViewModel
    {
    protected bool isSelected;
    public bool IsSelected
    {
    get => isSelected;
    set
    {
    SetProperty(ref isSelected, value);
    UpdateIconSource();
    }
    }
    private string menuTitle;
    public string MenuTitle
    {
    get => menuTitle;
    set => SetProperty(ref menuTitle, value);
    }

    private string iconSource;
    public string IconSource
    {
    get => iconSource;
    set => SetProperty(ref iconSource, value);
    }

    protected bool enableProperty;
    public bool EnableProperty
    {
    get => enableProperty;
    set => SetProperty(ref enableProperty, value);
    }

    protected void UpdateIconSource()
    {
    if (IsSelected)
    IconSource = “radiocheckmark.png”;
    else
    IconSource = “radioborder.png”;
    }

    }
    }

    Like

  2. Yes i checked your github repo, i cross checked my binding view models with yours, its the same way but i m getting empty flow list… statically flowlist is working but while dynamic binding its empty.. I want to show four radio buttons in horizontal manner

    Like

    1. try change your list radio button into this

      protected ObservableCollection listRadioButton;
      public ObservableCollection ListRadioButton
      {
      get => listRadioButton;
      set => SetProperty(ref listRadioButton, value);
      }

      Like

    1. sorry this is the right code

      protected ObservableCollection listRadioButton;
      public ObservableCollection ListRadioButton
      {
      get => listRadioButton;
      set => SetProperty(ref listRadioButton, value);
      }

      you need the object to make the obsevable collection

      Like

  3. Its okay sir, i m still not getting radio buttons in my flow list… i will check it n see if i can find any issues in my code .. thanks a lot for the help… highly appreciated!

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s