how to use radio buttons in xamarin forms

Viewed 46329

Creating a Registration page, I need to get the following data from user.

  • First Name
  • Last Name
  • Username
  • Email
  • Password
  • Date of Birth
  • Gender
  • User Role

For the last two parameters, I am unable to find how to use radio buttons in Xamarin.Forms. Following is my code for the Registration Page.

<StackLayout BackgroundColor="#30af91" Padding="60">


<Entry Text="{Binding FirstName}" Placeholder="First Name"/>
<Entry Text="{Binding LastName}" Placeholder="Last Name"/>
<Entry Text="{Binding UserName}" Placeholder="Last Name"/>
<Entry Text="{Binding Email}" Placeholder="Email" />
<Entry Text="{Binding Password}" Placeholder="Password" IsPassword="True"/>
<Entry Text="{Binding ConfirmPassword}" Placeholder="Confirm Password" IsPassword="True"/>
<DatePicker MinimumDate="1/1/1948" MaximumDate="12/31/2007"/>


<!--Radio buttons for Gender
    1. Male   2.Female-->

<!--Radio Buttons for UserRole
    1. Admin  2.Participant-->

<Button Command="{Binding RegisterCommand}" Text="Register"/>
<Label Text="{Binding Message}" />


</StackLayout>
11 Answers

I think there is a simpler solution that is fairly easy and requires no libraries. Really a a radio group is just a fancy ListView. You would just need to create a viewModel for each radio button that has a IsSelected flag and switch between 2 images. I had a need to allow a user to select how long a token persisted:

XAML

<ListView
    HasUnevenRows="True"
    HorizontalOptions="FillAndExpand"
    ItemsSource="{Binding Durations}"
    ItemSelected="ListView_ItemSelected"
    SelectedItem="{Binding SelectedDuration}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout
                    Orientation="Horizontal">
                    <Image
                        HeightRequest="18"
                        IsVisible="{Binding IsSelected}"
                        Source="radioButtonChecked.png"
                        WidthRequest="18"/>
                    <Image
                        HeightRequest="18"
                        IsVisible="{Binding IsUnselected}"
                        Source="radioButtonUnchecked.png"
                        WidthRequest="18"/>
                    <Label
                        Margin="8,0,0,0"
                        Text="{Binding Caption}"/>
                </StackLayout>
            </ViewCell>
         </DataTemplate>
      </ListView.ItemTemplate>
   </ListView>

We create a listview in our content page and listen for the ItemSelected event. Each list item is a horizontal stack panel where we flip between two images depending on the selected state

Code Behind

public partial class LoginPage : ContentPage
{
    LoginPageViewModel LoginPageViewModel { get; }

    public LoginTwoFactorFrequencyPage ()
    {
        BindingContext = LoginPageViewModel = new LoginPageViewModel();

        InitializeComponent ();
    }

    private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        LoginPageViewModel.UpdateSelected(e.SelectedItem as PersistenceDuration);
    }
}
  • The page's code behind instantiates a view model and calls an UpdateSelected method with the newly selected item on the page's view model*

RadioButton ViewModel

The view model for each radio button:

public class PersistenceDuration : ViewModelBase
{
    bool isSelected;

    public string Caption { get; set; }
    public TwoFactorTokenPersistenceDuration Duration { get; set; }
    public bool IsSelected
    {
        get => isSelected;
        set
        {
            isSelected = value;
            OnPropertyChanged();
            OnPropertyChanged("IsUnselected");
        }
    }
    public bool IsUnselected => !IsSelected;

    public PersistenceDuration(string caption, TwoFactorTokenPersistenceDuration duration)
    {
        Caption = caption;
        Duration = duration;
        IsSelected = false;
    }
}

The radio button view model holds selection info and the caption. We make sure to fire OnPropertyChanged whenever the selected state changes

Page ViewModel

public class LoginPageViewModel : ViewModelBase
{
    PersistenceDuration duration;
    PersistenceDuration selectedDuration;

    public ObservableCollection<PersistenceDuration> Durations { get; }
    public PersistenceDuration SelectedDuration
    {
        get => selectedDuration;
        set
        {
            if (value != null)
            {
                duration = value;
                UpdateSelected(duration);
            }
            OnPropertyChanged();
        }
    }

    public LoginTwoFactorFrequencyViewModel()
    {
        Durations = new ObservableCollection<PersistenceDuration>(
            new List<PersistenceDuration>()
            {
                new PersistenceDuration(AppResources.Save_code__forever, TwoFactorTokenPersistenceDuration.Forever),
                new PersistenceDuration(AppResources.ChatRequireEvery30Days, TwoFactorTokenPersistenceDuration.ThirtyDays),
                new PersistenceDuration(AppResources.ChatRequireEveryLogin, TwoFactorTokenPersistenceDuration.None),
            });
    }

    public void UpdateSelected(PersistenceDuration persistenceDuration)
    {
        foreach (var item in Durations)
            item.IsSelected = persistenceDuration == item;
    }
}

In the page view model we create a list of radio button view models that the XAML binds to. When we UpdateSelected() all the IsSelected states are updated which trigger binding updates which flip the image.

You will still need to do something about the highlight when someone selects an item, but that is easy enough to find on the internet :)

You can get the radio button effect without a package. Use Labels with text unicode circle \u26AA or \u25CB. Attach a tab gesture recognizer to each label.

When tapped, change the text of the selected button to unicode circle bullet \u29BF and change the text of the other button(s) back to unicode circle \u26AA.

Test on your preferred platforms as each platform may display somewhat differently. You may need to adjust the font size as you change the text.

Related