Google How to create RadioButton in Xamarin.Forms (C# - Xaml) | SubramanyamRaju Xamarin & Windows App Dev Tutorials

Tuesday, 13 March 2018

How to create RadioButton in Xamarin.Forms (C# - Xaml)

Introduction:
In Xamarin.Forms, there is no default RadioButton control available and we need to create our own custom RadioButton control. This article can explain you about to create RadioButton control and it's properties.  



Requirements:
  • This article source code was prepared by using Visual Studio Community for Mac (7.3.2). And it is better to install latest visual studio updates from here.
  • This sample project is Xamarin.Forms project and tested in Android emulator and iOS simulator.
Description:
This article can explain you below topics:
1. How to create Xamarin.Forms PCL project with Visual studio for Mac?
2. How to create RadioButton in Xamarin.Forms app?
3. How to use custom RadioButton in Xamarin.Forms?

1. How to create Xamarin.Forms PCL project with Visual studio for Mac?
Before to create RadioButton control, first we need to create the new Xamarin.Forms project. 
  • Launch Visual Studio for Mac.
  • On the File menu, select New Solution.
  • The New Project dialog appears. The left pane of the dialog lets you select the type of templates to display. In the left pane Multiplatform App Xamarin.Forms > Forms App and click on Next.
  • Enter your App Name (Ex: RadioButtonSample). Select Target Platforms to Android & iOS and Shared Code to Portable Class Library  after that click on Next button.


  • You can choose your project location like below and Create new project.


After that your new Xamarin.Forms will be load with default MVVM pattern which will have three folders name like ModelsViewsViewModels. So remove all files inside that folders and later we will add our own files in this article.

2. How to create RadioButton in Xamarin.Forms app?
If you search for RadioButton in Xamarin.Forms in internet you will find more resources to create RadioButton and you may find mostly two answers like below
1. We can create our own RadioButton by inheriting ContentView.
2. We can use Nuget package library like XLabs.form. But this is having more bugs and is no longer maintained, and even says so on the github repo.

In this article, we are choosing first option to create RadioButton by inheriting ContentView. And please follow below few steps for the same

Step 1: Create ContentView
We are following default MVVM design pattern. And here we will place custom controls in Controls folder. So right click on your project name RadioButton Sample => Add => New Folder name is "Controls". After that right click on your newly created the folder => Add => New File => Forms => Forms ContentView Xaml and name it RadioButton.

Step 2: Add UI to RadioButton
In general, RadioButton control required major four elements.
  • Title: Here we will take Label control to display title of RadioButton.
  • Border: Here we will take one Image control that will hold BorderImageSource.
  • Checkmark: Here we will take one Image control that will hold CheckMarkSource. And this check mark visibility should be based on user tap interaction which should deal by the some other property like IsChecked. I mean if IsChecked is True, check mark should be visible or else not visible.
  • Background: Here we will take one Image control that will hold BackGroundImageSource
So in your content view we need three Image controls and one label.
Now open RadioButton.xaml and add below code.

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="RadioButtonSample.Controls.RadioButton">  
  3.     <ContentView.Content>  
  4.         <StackLayout Orientation="Horizontal"  
  5.                      x:Name="mainContainer"  
  6.                      HorizontalOptions="FillAndExpand"  
  7.                      VerticalOptions="FillAndExpand"  
  8.                      Padding="0"  
  9.                      Spacing="5">  
  10.             <AbsoluteLayout HorizontalOptions="Center"  
  11.                             VerticalOptions="Center"  
  12.                             WidthRequest="20"  
  13.                             HeightRequest="20"  
  14.                             x:Name="imageContainer">  
  15.                 <Image Source="{Binding CheckedBackgroundImageSource}"  
  16.                        x:Name="checkedBackground"  
  17.                        Aspect="AspectFit"  
  18.                        AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"  
  19.                        AbsoluteLayout.LayoutFlags="All"  
  20.                        Opacity="0"  
  21.                        InputTransparent="True"/>  
  22.                 <Image Source="{Binding BorderImageSource}"  
  23.                        x:Name="borderImage"  
  24.                        Aspect="AspectFit"  
  25.                        AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"  
  26.                        AbsoluteLayout.LayoutFlags="All"  
  27.                        InputTransparent="True"/>  
  28.                 <Image Source="{Binding CheckmarkImageSource}"  
  29.                        x:Name="checkedImage"  
  30.                        Aspect="AspectFit"  
  31.                        AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"  
  32.                        AbsoluteLayout.LayoutFlags="All"  
  33.                        Opacity="0"  
  34.                        InputTransparent="True"/>  
  35.             </AbsoluteLayout>  
  36.             <Label x:Name="controlLabel"  
  37.                    HorizontalOptions="FillAndExpand"  
  38.                    VerticalOptions="FillAndExpand"  
  39.                    HorizontalTextAlignment="Start"  
  40.                    VerticalTextAlignment="Center"  
  41.                    Text="{Binding Title}"  
  42.                    Style="{Binding LabelStyle}"  
  43.                    InputTransparent="True"/>  
  44.         </StackLayout>  
  45.     </ContentView.Content>  
  46. </ContentView>  

Step 3: Add properties to RadioButton
We are going to add below Bindable properties for our RadioButton control.
  • TitleProperty: To bind tile of check box.
  • LabelStyleProperty: To to set style to Title label.
  • IsCheckedProperty: To maintain RadioButton states for check or uncheck.
  • BorderImageSourceProperty: To set Border image for RadioButton.
  • CheckedBackgroundImageSourceProperty:To set Background image for RadioButton.
  • CheckMarkImageSourceProperty: To set CheckMark image for RadioButton.
  • CheckedChangedCommandProperty:  To make interaction with RadioButton when user tap on it's main container.
Also we are applying animation while check box taking up check mark and hiding it.

Now open RadioButton.Xaml.cs and add below code.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using Xamarin.Forms;  
  4. using Xamarin.Forms.Xaml;  
  5.   
  6. namespace RadioButtonSample.Controls  
  7. {  
  8.     /// <summary>  
  9.  /// Custom RadioButton control  
  10.  /// </summary>  
  11.     [XamlCompilation(XamlCompilationOptions.Compile)]  
  12.   
  13.     public partial class RadioButton : ContentView  
  14.     {  
  15.         public RadioButton()  
  16.         {  
  17.             InitializeComponent();  
  18.             controlLabel.BindingContext = this;  
  19.             checkedBackground.BindingContext = this;  
  20.             checkedImage.BindingContext = this;  
  21.             borderImage.BindingContext = this;  
  22.             mainContainer.GestureRecognizers.Add(new TapGestureRecognizer()  
  23.             {  
  24.                 Command = new Command(tapped)  
  25.             });  
  26.         }  
  27.   
  28.         public static readonly BindableProperty BorderImageSourceProperty = BindableProperty.Create(nameof(BorderImageSource), typeof(string), typeof(RadioButton), "", BindingMode.OneWay);  
  29.         public static readonly BindableProperty CheckedBackgroundImageSourceProperty = BindableProperty.Create(nameof(CheckedBackgroundImageSource), typeof(string), typeof(RadioButton), "", BindingMode.OneWay);  
  30.         public static readonly BindableProperty CheckmarkImageSourceProperty = BindableProperty.Create(nameof(CheckmarkImageSource), typeof(string), typeof(RadioButton), "", BindingMode.OneWay);  
  31.         public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create(nameof(IsChecked), typeof(bool), typeof(RadioButton), false, BindingMode.TwoWay, propertyChanged: checkedPropertyChanged);  
  32.         public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(RadioButton), "", BindingMode.OneWay);  
  33.         public static readonly BindableProperty CheckedChangedCommandProperty = BindableProperty.Create(nameof(CheckedChangedCommand), typeof(Command), typeof(RadioButton), null, BindingMode.OneWay);  
  34.         public static readonly BindableProperty LabelStyleProperty = BindableProperty.Create(nameof(LabelStyle), typeof(Style), typeof(RadioButton), null, BindingMode.OneWay);  
  35.   
  36.         public string BorderImageSource  
  37.         {  
  38.             get { return (string)GetValue(BorderImageSourceProperty); }  
  39.             set { SetValue(BorderImageSourceProperty, value); }  
  40.         }  
  41.   
  42.         public string CheckedBackgroundImageSource  
  43.         {  
  44.             get { return (string)GetValue(CheckedBackgroundImageSourceProperty); }  
  45.             set { SetValue(CheckedBackgroundImageSourceProperty, value); }  
  46.         }  
  47.   
  48.         public string CheckmarkImageSource  
  49.         {  
  50.             get { return (string)GetValue(CheckmarkImageSourceProperty); }  
  51.             set { SetValue(CheckmarkImageSourceProperty, value); }  
  52.         }  
  53.   
  54.         public bool IsChecked  
  55.         {  
  56.             get { return (bool)GetValue(IsCheckedProperty); }  
  57.             set { SetValue(IsCheckedProperty, value); }  
  58.         }  
  59.   
  60.         public string Title  
  61.         {  
  62.             get { return (string)GetValue(TitleProperty); }  
  63.             set { SetValue(TitleProperty, value); }  
  64.         }  
  65.   
  66.         public Command CheckedChangedCommand  
  67.         {  
  68.             get { return (Command)GetValue(CheckedChangedCommandProperty); }  
  69.             set { SetValue(CheckedChangedCommandProperty, value); }  
  70.         }  
  71.   
  72.         public Style LabelStyle  
  73.         {  
  74.             get { return (Style)GetValue(LabelStyleProperty); }  
  75.             set { SetValue(LabelStyleProperty, value); }  
  76.         }  
  77.   
  78.         public Label ControlLabel  
  79.         {  
  80.             get { return controlLabel; }  
  81.         }  
  82.   
  83.         static void checkedPropertyChanged(BindableObject bindable, object oldValue, object newValue)  
  84.         {  
  85.             ((RadioButton)bindable).ApplyCheckedState();  
  86.         }  
  87.   
  88.         void tapped()  
  89.         {  
  90.             if (!IsChecked)  
  91.                 IsChecked = true;  
  92.             setCheckedState(IsChecked);  
  93.             if (CheckedChangedCommand != null && CheckedChangedCommand.CanExecute(this))  
  94.                 CheckedChangedCommand.Execute(this);  
  95.         }  
  96.   
  97.         /// <summary>  
  98.         /// Reflect the checked event change on the UI  
  99.         /// with a small animation  
  100.         /// </summary>  
  101.         /// <param name="isChecked"></param>  
  102.         void setCheckedState(bool isChecked)  
  103.         {  
  104.             Animation storyboard = new Animation();  
  105.             Animation fadeAnim = null;  
  106.             Animation checkBounceAnim = null;  
  107.             Animation checkFadeAnim = null;  
  108.             double fadeStartVal = 0;  
  109.             double fadeEndVal = 1;  
  110.             double scaleStartVal = 0;  
  111.             double scaleEndVal = 1;  
  112.             Easing checkEasing = Easing.CubicIn;  
  113.   
  114.             if (isChecked)  
  115.             {  
  116.                 checkedImage.Scale = 0;  
  117.                 fadeStartVal = 0;  
  118.                 fadeEndVal = 1;  
  119.                 scaleStartVal = 0;  
  120.                 scaleEndVal = 1;  
  121.                 checkEasing = Easing.CubicIn;  
  122.             }  
  123.             else  
  124.             {  
  125.                 fadeStartVal = 1;  
  126.                 fadeEndVal = 0;  
  127.                 scaleStartVal = 1;  
  128.                 scaleEndVal = 0;  
  129.                 checkEasing = Easing.CubicOut;  
  130.             }  
  131.             fadeAnim = new Animation(  
  132.                     callback: d => checkedBackground.Opacity = d,  
  133.                     start: fadeStartVal,  
  134.                     end: fadeEndVal,  
  135.                     easing: Easing.CubicOut  
  136.                     );  
  137.             checkFadeAnim = new Animation(  
  138.                 callback: d => checkedImage.Opacity = d,  
  139.                 start: fadeStartVal,  
  140.                 end: fadeEndVal,  
  141.                 easing: checkEasing  
  142.                 );  
  143.             checkBounceAnim = new Animation(  
  144.                 callback: d => checkedImage.Scale = d,  
  145.                 start: scaleStartVal,  
  146.                 end: scaleEndVal,  
  147.                 easing: checkEasing  
  148.                 );  
  149.   
  150.             storyboard.Add(0, 0.6, fadeAnim);  
  151.             storyboard.Add(0, 0.6, checkFadeAnim);  
  152.             storyboard.Add(0.4, 1, checkBounceAnim);  
  153.             storyboard.Commit(this"checkAnimation", length: 600);  
  154.         }  
  155.   
  156.         public void ApplyCheckedState()  
  157.         {  
  158.             setCheckedState(IsChecked);  
  159.         }  
  160.     }  
  161. }  
We complete creation of RadioButton and it will also support data binding. So we can dynamically supply all properties of RadioButton.

4. How to use custom RadioButton in Xamarin.Forms?

Now we are ready to our own RadioButton control. Before to use it, let's create one ContentPage in Views folder.

To create page, right click on Views folder => Add =>New File => Forms => Forms ContentPage Xaml and name it HomePage like below.


To use RadioButton in our xaml page. First we need declare namespace of RadioButton.
  1. xmlns:ctrls="clr-namespace:RadioButtonSample.Controls"  
And then we can use RadioButton like below
  1. <ctrls:RadioButton x:Name="cbIndia" Title="India" IsChecked="True" BorderImageSource="radioborder" CheckedBackgroundImageSource="radiocheckedbg" CheckmarkImageSource="radiocheckmark" />  

Here we set the values for the RadioButton properties are 
Title: India
IsChecked: True
BorderImageSource: radioborder.png
CheckBackgroundImageSource: radiocheckedbg.png
CheckmarkImageSource: radiocheckmark.png

We should add all above images to Android drawable folder and for iOS Resources folder.

Now open HomePage.xaml file, add below total source code.
  • <?xml version="1.0" encoding="UTF-8"?>    
  • <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"     
  •     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"    
  •     x:Class="RadioButtonSample.Views.HomePage"    
  •     xmlns:ctrls="clr-namespace:RadioButtonSample.Controls" >    
  •     <StackLayout Margin="20" x:Name="stackPanel">    
  •         <Label Text="Select Country" FontSize="25" FontAttributes="Bold" />    
  •         <ctrls:RadioButton x:Name="cbIndia" Title="India" IsChecked="True" BorderImageSource="radioborder" CheckedBackgroundImageSource="radiocheckedbg" CheckmarkImageSource="radiocheckmark" />    
  •     </StackLayout>    
  • </ContentPage>    
  • For example, if you want to use RadioButton from code behind.
    1. void CreateRadioButton()  
    2.        {  
    3.            RadioButton radioButton = new RadioButton();  
    4.            radioButton.IsChecked = false;  
    5.            radioButton.IsVisible = true;  
    6.            radioButton.Title = "Japan";  
    7.            radioButton.BorderImageSource = "radioborder";  
    8.            radioButton.CheckedBackgroundImageSource = "radiocheckedbg";  
    9.            radioButton.CheckmarkImageSource = "radiocheckmark";  
    10.            stackPanel.Children.Add(radioButton);  
    11.        }  
    For example, if you want to bind RadioButton from code behind.
    1. void RadioButtonBinding()  
    2.        {  
    3.            Country country = new Country();  
    4.            country.Name = "Singapore";  
    5.            country.IsSelected = false;  
    6.            country.IsVisible = true;  
    7.   
    8.            RadioButton radioButton = new RadioButton();  
    9.            radioButton.BindingContext = country;  
    10.            radioButton.SetBinding(RadioButton.IsCheckedProperty, "IsSelected", BindingMode.TwoWay);  
    11.            radioButton.SetBinding(RadioButton.IsVisibleProperty, "IsVisible");  
    12.            radioButton.SetBinding(RadioButton.TitleProperty, "Name");  
    13.            radioButton.BorderImageSource = "radioborder";  
    14.            radioButton.CheckedBackgroundImageSource = "radiocheckedbg";  
    15.            radioButton.CheckmarkImageSource = "radiocheckmark";  
    16.            stackPanel.Children.Add(radioButton);  
    17.        }  
    In above code, we bind the RadioButton with Country class object properties (Name, IsSelected, IsVisibile). So let's create Country Class in Model folder. To create class, right click on Models folder => Add =>New File => General => Empty Class and name it Country like below.
    Now open Country class and add below properties.
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.ComponentModel;  
    4. using System.Runtime.CompilerServices;  
    5.   
    6. namespace RadioButtonSample  
    7. {  
    8.     public class Country: INotifyPropertyChanged  
    9.     {  
    10.         public string Name { getset; }  
    11.   
    12.         bool isVisible;  
    13.         public bool IsVisible  
    14.         {  
    15.             get { return isVisible; }  
    16.             set { SetProperty(ref isVisible, value); }  
    17.         }  
    18.   
    19.         bool isSelected;  
    20.         public bool IsSelected  
    21.         {  
    22.             get { return isSelected; }  
    23.             set { SetProperty(ref isSelected, value); }  
    24.         }  
    25.         protected bool SetProperty<T>(ref T backingStore, T value,  
    26.             [CallerMemberName]string propertyName = "",  
    27.             Action onChanged = null)  
    28.         {  
    29.             if (EqualityComparer<T>.Default.Equals(backingStore, value))  
    30.                 return false;  
    31.   
    32.             backingStore = value;  
    33.             onChanged?.Invoke();  
    34.             OnPropertyChanged(propertyName);  
    35.             return true;  
    36.         }  
    37.  
    38.         #region INotifyPropertyChanged  
    39.         public event PropertyChangedEventHandler PropertyChanged;  
    40.         protected void OnPropertyChanged([CallerMemberName] string propertyName = "")  
    41.         {  
    42.             var changed = PropertyChanged;  
    43.             if (changed == null)  
    44.                 return;  
    45.   
    46.             changed.Invoke(thisnew PropertyChangedEventArgs(propertyName));  
    47.         }  
    48.         #endregion  
    49.     }  
    50. }  
    Let's see overview of total source code of HopePage.xaml.cs file.
    1. using RadioButtonSample.Controls;  
    2. using RadioButtonSample.ViewModels;  
    3. using Xamarin.Forms;  
    4.   
    5. namespace RadioButtonSample.Views  
    6. {  
    7.     public partial class HomePage : ContentPage  
    8.     {  
    9.         HomeViewModel _homeViewModel;  
    10.         public HomePage()  
    11.         {  
    12.             InitializeComponent();   
    13.             CreateRadioButton();  
    14.             RadioButtonBinding();  
    15.         }  
    16.   
    17.         /// <summary>  
    18.         /// Creating RadioButton with assigned values (Bg, border, title, selection)  
    19.         /// </summary>  
    20.         void CreateRadioButton()  
    21.         {  
    22.             RadioButton radioButton = new RadioButton();  
    23.             radioButton.IsChecked = false;  
    24.             radioButton.IsVisible = true;  
    25.             radioButton.Title = "Japan";  
    26.             radioButton.BorderImageSource = "radioborder";  
    27.             radioButton.CheckedBackgroundImageSource = "radiocheckedbg";  
    28.             radioButton.CheckmarkImageSource = "radiocheckmark";  
    29.             stackPanel.Children.Add(radioButton);  
    30.         }  
    31.   
    32.         /// <summary>  
    33.         /// RadioButton binding with homeViewModel  
    34.         /// </summary>  
    35.         void RadioButtonBinding()  
    36.         {  
    37.             Country country = new Country();  
    38.             country.Name = "Singapore";  
    39.             country.IsSelected = false;  
    40.             country.IsVisible = true;  
    41.   
    42.             RadioButton radioButton = new RadioButton();  
    43.             radioButton.BindingContext = country;  
    44.             radioButton.SetBinding(RadioButton.IsCheckedProperty, "IsSelected", BindingMode.TwoWay);  
    45.             radioButton.SetBinding(RadioButton.IsVisibleProperty, "IsVisible");  
    46.             radioButton.SetBinding(RadioButton.TitleProperty, "Name");  
    47.             radioButton.BorderImageSource = "radioborder";  
    48.             radioButton.CheckedBackgroundImageSource = "radiocheckedbg";  
    49.             radioButton.CheckmarkImageSource = "radiocheckmark";  
    50.             stackPanel.Children.Add(radioButton);  
    51.         }  
    52.     }  
    53. }  

    Demo Screens from Android:

    Demo Screens from iOS:

    You can directly work on below sample source code to understand the this article. 
    RadioButtonSample

    FeedBack Note: Please share your thoughts, what you think about this post, Is this post really helpful for you? Otherwise, it would be very happy, if you have any thoughts for to implement this requirement in any other way? I always welcome if you drop comments on this post and it would be impressive.

    Follow me always at @Subramanyam_B
    Have a nice day by  :)

    1 comment:

    1. Hello, would you be so kind and provide me images you used in the exampla? Thank you.

      ReplyDelete

    Search Engine Submission - AddMe