Resource Page DescriptionThis page shows how to re-style a ListBox to create a RadioButtonList.
Also, it shows how to display a nullable boolean value as Yes / No / (no selection) using the (Horizontal) RadioButtonList style.
The problem
There is currently no RadioButtonList control in WPF.
The workaround
A RadioButtonList is essentially an ItemsControl, and WPF allows us to completely re-style the UI for controls, so we don't need a RadioButtonList after all.
The following example (partially inspired by Dr. WPF's forum reply
here) shows a style for a ListBox which renders items as a Horizontal RadioButtonList (for a Vertical RadioButtonList simply change the Orientation property of the VirtualizingStackPanel - or remove it, as Vertical is the default).
<Style x:Key="HorizontalRadioButtonList" TargetType="{x:Type ListBox}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel Background="Transparent" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem}" >
<Setter Property="Margin" Value="5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border BorderThickness="0" Background="Transparent">
<RadioButton Focusable="False"
IsHitTestVisible="False"
IsChecked="{TemplateBinding IsSelected}">
<ContentPresenter />
</RadioButton>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<Border BorderThickness="0" Padding="0" BorderBrush="Transparent" Background="Transparent" Name="Bd" SnapsToDevicePixels="True">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have chosen to make the control take on the settings of it's parent (i.e. the Panel it is contained within) as much as possible (by using Transparent colours, collapsing borders etc.).
Recently, I needed a control to allow a user to select a Yes or No RadioButton or to leave it 'unset' - i.e. to set a nullable boolean (bit in SQL Server 2005) value in the database.
The following example accomplishes this with the help of a nullable boolean ValueConverter described
here:
<ListBox Name="lbAchieved"
Style="{StaticResource HorizontalRadioButtonList}"
SelectedValue="{Binding Path=IsAchieved, Converter={StaticResource nullableBooleanConverter}}"
SelectedValuePath="Tag">
<ListBoxItem Tag="True">Yes</ListBoxItem>
<ListBoxItem Tag="False">No</ListBoxItem>
</ListBox>
The user can 'unset' a RadioButton by holding the Ctrl key and clicking the left mouse button (using some handy ListBox behaviour).