WPF RadioButtons: Choices, Choices

Radio buttons are a common way for a user to select a single choice from several options. In this post, I’ll go over several ways of using RadioButtons in the Microsoft .Net Windows Presentation Foundation (WPF) framework.

The Basic RadioButton

The first thing to know about WPF RadioButtons is that, unless otherwise specified, all RadioButtons within a container element (e.g. Grid, StackPanel) are assumed to be members of the same group. So a simple way to include a group of RadioButtons in a view is to do something like this:

<StackPanel>
   <RadioButton Content="Turkey" 
                         IsChecked="True"
                         Margin="5,1"/>
   <RadioButton Content="Ham"
                         Margin="5,1"/>
   <RadioButton Content="Goose"
                         Margin="5,1"/>
</StackPanel>

If you’d like to include two different groups of RadioButtons within the same container, give the RadioButtons in at least one of the groups a GroupName attribute, like this:

<StackPanel>
 
   <!-- Main Course -->
   <TextBlock Text="Select a Main Course"
                       FontSize="18"
                       Margin="5" />
   <RadioButton Content="Turkey" 
                         IsChecked="True"
                         Margin="5,1"/>
   <RadioButton Content="Ham"
                         Margin="5,1"/>
   <RadioButton Content="Goose"
                         Margin="5,1"/>
 
   <!-- Starch -->
   <TextBlock Text="Select a Starch"
                       FontSize="18"
                        Margin="5" />
   <RadioButton GroupName="Starch"
                         Content="Mashed Potatoes"
                         Margin="5,1"/>
   <RadioButton GroupName="Starch"
                         Content ="Dinner Roll"
                         IsChecked="True"
                         Margin="5,1"/>
   <RadioButton GroupName="Starch"
                         Content="Rice Pilaf"
                         Margin="5,1"/>
 
</StackPanel>

Dynamic RadioButtons with an ItemsControl

What if you have a dynamic list of choices that you want to databind your RadioButtons to? One way to do this is to use an ItemsControl and databind its ItemsSource property to a collection of choices in your view model.

First, let’s introduce a class that represents the different choices:

    public class SelectableItem : INotifyPropertyChanged
    {
        public string ItemDescription { get; set; }
 
        public bool IsSelected { get; set; }
 
        public event PropertyChangedEventHandler PropertyChanged;
    }

Now in our view model we have a collection of SelectableItems:

    public class MainWindowViewModel : INotifyPropertyChanged
    {
        public MainWindowViewModel()
        {
            Salads = new Collection<SelectableItem>
                {
                    new SelectableItem { ItemDescription = "Kale Avocado"},
                    new SelectableItem { ItemDescription = "Caesar"},
                    new SelectableItem { ItemDescription = "Arugula with Goat Cheese", IsSelected = true},
                    new SelectableItem { ItemDescription = "Garden"}
                };
        }
 
        // Salads
        public Collection<SelectableItem> Salads { get; set; }
 
        public SelectableItem SelectedSalad
        {
            get { return Salads.FirstOrDefault(s => s.IsSelected); }
        }
 
        // Property Changed
        public event PropertyChangedEventHandler PropertyChanged;
    }

Finally, in our view we have the following xaml:

<StackPanel Grid.Row="2">
   <TextBlock Text="Select a Salad"
                       FontSize="18"
                        Margin="5" />
   <ItemsControl ItemsSource="{Binding Salads}">
      <ItemsControl.ItemTemplate>
           <DataTemplate>
               <RadioButton GroupName="Salads"
                            Content="{Binding ItemDescription}"
                            IsChecked="{Binding IsSelected}"
                            Margin="5,1"/>
           </DataTemplate>
 
       </ItemsControl.ItemTemplate>
   </ItemsControl>
</StackPanel>

A couple of things to note when using this technique:

  • You need to include a GroupName attribute in the RadioButton element within the ItemTemplate, otherwise each of the RadioButtons in the ItemsControl will work independently of the others.
  • We haven’t databound the SelectedSalad property in MainWindowViewModel to anything. It’s included to show you how you might determine which of the Salads is the one currently selected in the view. If you must respond every time the user changes her Salad selection (for instance, if you need to save the selection to a database), you might include the logic for this in the SelectableItem class.

Dynamic RadioButtons with a ListBox

An interesting thing to observe about a group of RadioButtons is that their behavior is identical to a single selection ListBox. The differences between a group of RadioButtons and a ListBox are entirely visual. One advantage of a ListBox is that it has a SelectedItem property, which can be databound to a property on a view model, making it convenient to keep track of the currently selected item and perform any logic that is necessary when the selected item changes.

Let’s adapt our view model to allow us to databind to a ListBox:

    public class MainWindowViewModel : INotifyPropertyChanged
    {
        public MainWindowViewModel()
        {
            VegetableDishes = new Collection<string>
                                    { 
                                        "Butternut Squash Soufle", 
                                        "Roasted Celery Root", 
                                        "Sauteed Brussel Sprouts", 
                                        "Glazed Carrots"
                                    };
            SelectedVegetableDish = VegetableDishes.Last();
        }
 
        // Vegetables
        public ICollection<string> VegetableDishes { get; set; }
 
        private string selectedVegetableDish;
        public string SelectedVegetableDish
        {
            get { return selectedVegetableDish; }
            set 
            { 
                selectedVegetableDish = value;
                onNotifyPropertyChanged("SelectedVegetableDish");
                // Logic for saving to database
            }
        }
 
        // Property Changed
        public event PropertyChangedEventHandler PropertyChanged;
 
        private void onNotifyPropertyChanged(string propertyName)
        {
            var eventToFire = PropertyChanged;
            if (eventToFire != null)
                eventToFire(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Now in our xaml we can make our ListBox look like a group of RadioButtons like this:

        <StackPanel Grid.Row="1">
            <TextBlock Text="Select a Vegetable"
                       FontSize="18"
                        Margin="5" />
            <ListBox ItemsSource="{Binding VegetableDishes}"
                     SelectedItem="{Binding SelectedVegetableDish}"
                     BorderBrush="Transparent"
                     BorderThickness="0"
                     ItemTemplate="{StaticResource ListBoxItemTemplate}"/>
        </StackPanel>

I’ve done a couple of things here to make my ListBox look like a plain old collection of RadioButtons. First, I re-template the ListBoxItem so that it doesn’t highlight the selected row. Second, I have created an ItemTemplate that uses a RadioButton for each item in the ListBox. The RadioButton’s IsChecked property is databound to the IsSelected property of the ListBoxItem that contains it. (Recall that all ItemsControls place each Item inside of a container. For a ListBox, that container is a ListBoxItem.)

    <Window.Resources>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                                      Margin="5,1"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        </Style>
 
        <DataTemplate x:Key="ListBoxItemTemplate">
            <RadioButton Content="{Binding}"
                                 IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" />
        </DataTemplate>
 
    </Window.Resources>

Binding RadioButtons to an Enum

Finally, what if we want to databind our RadioButtons to an enum? Let’s say we have the following:

    public enum DessertEnumeration
    {
        PumpkinPie,
        ApplePie,
        PecanPie,
        SweetPotatoPie,
    }

We can add the following properties to our view model:

        // Dessert
        public Array Desserts
        {
            get { return Enum.GetValues(typeof(DessertEnumeration)); }
        }
 
        private DessertEnumeration selectedDessert;
        public DessertEnumeration SelectedDessert
        {
            get { return selectedDessert; }
            set 
            { 
                selectedDessert = value;
                onNotifyPropertyChanged("SelectedDessert");
                // save to database
            }
        }

And finally, here is our xaml:

        <!-- Dessert -->
        <StackPanel Grid.Row="3">
            <TextBlock Text="Select a Dessert"
                       FontSize="18"
                        Margin="5" />
            <ListBox ItemsSource="{Binding Desserts}"
                     SelectedItem="{Binding SelectedDessert}"
                     BorderBrush="Transparent"
                     BorderThickness="0"
                     ItemTemplate="{StaticResource ListBoxItemTemplate}"/>
 
        </StackPanel>

The technique you use when working with RadioButtons will depend on the source for your choices and what you want to do when the selected option changes. Here is what all of the RadioButtons in the sample code above look like:

radioButtons