WPF Data Bound RadioButtonList


During the process of writing a WPF application recently, I had the need for a data bound list of items where the options had to be mutually exclusive, so I figured something like a list of RadioButtons would be in order.

However, when I started looking around I could not find a RadioButtonList or anything that fitted the bill out-of-the-box. Therefore, I thought I’d put something together myself; I also needed to have the list render horizontally rather than vertically. This is what I came up with:

<!-- Item Style for the ListBoxItem to add a RadioButton -->
<Style x:Key="RadioButtonItemStyle" TargetType="{x:Type ListBoxItem}">
    <Setter Property="Margin" Value="0,0,5,0" />
    <Setter Property="Template">
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <Border BorderThickness="0" Background="Transparent">
                    <!-- Note: IsChecked is bound to IsSelected-->
                        IsChecked="{TemplateBinding IsSelected}">
                        <ContentPresenter />

<!-- Turns the ListBox in to a Horizontal ListBox -->
<ItemsPanelTemplate x:Key="HorizontalItemsPanel">
        Orientation="Horizontal" />

I defined a Style and the ItemsPanelTemplate in the Resources property of my Window that contains all the necessary XAML for the effects I need; note that you could just as easily define this XAML inline on the ListBox as opposed to using the Resources property. I then applied these two new elements to an instance of ListBox using the following mark-up:

    ItemsSource="{Binding MyDataList}"
    SelectedValue="{Binding MyDataListSelectedValue}"
    ItemContainerStyle="{StaticResource RadioButtonItemStyle}"
    ItemsPanel="{StaticResource HorizontalItemsPanel}" />

I’ve highlighted where I’ve used the two resources.

For this example the data list is trivial and is provided by a ViewModel class attached to the DataContext of the Window; I’m only showing the code here as a example of how you can add sample data to an application, as well as proving that the above XAML all works as expected using a bound list of data:

public class MainWindowViewModel
    public IEnumerable<string> MyDataList
            yield return "Stan";
            yield return "Cartman";
            yield return "Kenny";
            yield return "Karl";

    public string MyDataListSelectedValue
        get { return "Cartman"; }
        set { /* TODO: save the value */ }

<!-- XAML -->
    <vm:MainWindowViewModel />

Here’s what it all looks like in the Visual Studio designer:


And there we have it, job done. Hope this helps someone, happy XAML hacking.


Derek Lakin said...

Any ideas when you start to see benefits to using a VirtualizingStackPanel? I'm guessing at such low numbers there isn't really any benefit?

Paul said...

You're absolutely right about the low numbers here; you could simply use a StackPanel. I would also argue that with something like a RadioButtonList you would never really have enough elements to warrant a virtualized panel.

However, as a best practice I would always attempt to keep the template as close to the original control template as possible. There are a number of reasons for this, not least of which is the "special" un-written contracts with some control templates, where the WPF developers have done some optimizations or provided additional behaviour if they find elements of a certain type or find element of a certain type and with a specific name e.g. PART_nnn (ScrollBar, ProgressBar and TextBox are all good example of this).


Brownie said...

Here's a post on the Forums from Dr. WPF on using a style to create a radio button list


Vijay said...

Really Great Post