Introduction
Silverlight 2 has a couple of useful controls, which you can use when building your own applications. This collection of controls is extended by Silverlight Toolkit. It contains really great controls like Expander, AutoCompleteBox, TreeView, etc. You can download the Silverlight Toolkit from its site or you can see the online demo.
Imagine that you want to create a questionnaire. A questionnaire consists of questions and a list of possible answers for each question. In most occasions you are supposed to select just an answer. Translated into Silverlight language, that means you need TextBlock for each question and a list of RadioButtons for the possible answers. Let’s go further creating our Silverlight questionnaire application.
Beginning
First, we have to create the architecture of our application. It will be as simple as possible.

The Questionnaire project contains the Silverlight application. Questionnaire.Business contains our business objects. Questionnaire.Controls contains the main controls, which we will use in the application.

In this example the data source is in an static class, called QuestionStore. You can use a XML file, or call a web service. But for the purpose of the example, I did it the simplest way.
The Problem
The problem is clear – we need a control that represents a list of radio buttons. As you may know neither the collection of built-in Silverlight controls nor the Silverlight Toolkit contains such a control. Well, in Silverlight world, when we do not have something, we create it. So, in our occasion we can create a custom user control, which will do the great job to contain many radio buttons. Silverlight has a built-in RadioButton control, which we will use. However, creating an entirely new control would make our work more complicated. We would better extend an already existing control, which has the base functionality, needed by our control. Or we can even use an existing control and change its template. Let’s try this first!
Using the ItemsControl - First Try to Solve Our Problem
Because we are very lazy, we want to try the simplest way first. And I think that the simplest way is using the ItemsControl. ItemsControl is the base control for all controls which display items. Such a control is ListBox, ComboBox, etc. I will talk about these controls later in the article. So, all we need is to modify the style of the items in the ItemsControl. Each item will be a RadioButton. In such way we will simulate a real radio list.
<ItemsControl x:Name="radioList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<RadioButton Content="{Binding}" GroupName="abc" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
public Page()
{
...
radioList.ItemsSource = new string[] { "Item 1", "Item 2", "Item 3", "Item 4" };
}
The ItemTemplate property of the ItemsControl let us set how each item will be visualized. We are using just a RadioButton control, and bind its Content property to the source, which is specified (in our occasion, the source is the array we set in the code-behind). But what makes our radio buttons be in one group – so we can select no more than an option? If you have a look in the items template, that we set, you can see the GroupName property of the RadioButton. This property lets you specific the name of group, which each radio button belongs to. This makes sure that only one radio button is selectd in a group. Sounds good, right? But let’s have a look at the result of our code:

Very good! But, hey, why two options are selected? Didn’t we set these radio buttons to be in the same group? Yes we did! After some meddling with the code, it looks like, as of RC0, that the scope of GroupName for custom controls appears to be limited to the control itself. It seems like a bug. But, reading the Silverlight official forum, I understood that it is not a bug, but a feature. Here is the answer of Yi-Lun Luo in the Silverlight official forum:
“Hello, this change is reasonable. Let's say you're using a third party Control called VoteControl, whose Template has a series of RadioButtons whose GroupName are set to group1. But you don't know anything about the GroupName until you have a close look at the default Template. Now you have added 2 instances of that VoteControl on your UserControl, and you have several other RadioButtons in this UserControl, whose GroupName are also group1. What is the result you expect? I think most people will want to see 3 groups of RadioButtons instead of 1. If the actual result is all RadioButtons are in the same group, you have to create a Template for each VoteControl and give the RadioButtons a different GroupName in order to get the desired result...”
It seems like most of the users do not like this change. I don’t like it, too! In the beta versions of Silverlight, this code was working perfectly. Well, now we can look for a workaround of this problem. One of the suggestions is to manage the IsChecked property of the RadioButtons manually via code by using VisualTreeHelper to walk the contents of the ItemsControl after it is databound. Using the Checked event, you should call your function to uncheck the previous checked radio button.
private void RadioButton_Checked(object sender, RoutedEventArgs e)
{
RadioButton radio = (RadioButton)sender;
UncheckGroupRadioButtons(...);
}
Using the ListBox – Second Try to Solve Our Problem
Well, the simplest way didn’t help us. Let’s think something else. If you have a look at the ListBox control, you will see how closer it is to what we want:
- It supports items (because it extends the ItemsControl)
- It has properties to manage with the selected item (SelectedIndex and SelectedItem)
The only thing that is different is its look. But, do not forget that in Silverlight we can easily change this.
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid Background="Transparent">
<RadioButton IsChecked="{TemplateBinding IsSelected}" IsHitTestVisible="False">
<ContentPresenter/>
</RadioButton>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>

Well, it seems like this is the solution of our problem! Now we can check only one radio button. What is difference between these two versions? We have bound the IsChecked property of the RadioButton to the IsSelected property of the ListBoxItem. Note the usage of the IsHitTestVisible – it is set to false. In this way, the radio button won’t participate in the hit test, so you cannot check it. If you set it to True, you will be able to select more than one option, which is not the desired result. Note also that the Grid must have a background in order to do hit test.
Creating the RadioList Control
If we want to reuse this modification of the ListBox control, we’d better create a custom control – RadioList. Here is what we have to do:
- Create a new class, called RadioListItem. It will inherit the existing ListBoxItem. It will add two new properties: Key and Value. Each of these properties should be a DependencyProperty! This class will let us specify items with a key and a value. This is very useful, as we may want to specify a key for each item. The other option is to use the SelectedIndex property as a key for the selected item.
- Create a new class, called RadioList. As you know, this class will inherit the existing ListBox control.
Now, we have to do a few things more. When working with ItemsControl, you should know for these methods:
- GetContainerForItemOverride – it creates a new item, which will be used when displaying the bound one. What does this mean? This method specifies the object, which our control will use to encapsulate the bound item. For example, you can set the ItemsSource to an array of strings. In this method you should specify the object, which the RadioList control should work with – in our occasion this is an instance of the RadioListItem.
protected override DependencyObject GetContainerForItemOverride()
{
return new RadioListItem();
}
- IsItemItsOwnContainerOverride – it determines if the specified item is or is eligible to be its own container. We have to check is an item is a RadioListItem.
protected override bool IsItemItsOwnContainerOverride(object item)
{
return (item is RadioListItem);
}
- PrepareContainerForItemOverride – this is very important method. It lets you specify how each item will be displayed. For example, you set the ItemsSource to an array of strings. But the control knows how to display RadioListItems only. So in this method you should specify how to display each string.
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
if (element != item)
{
RadioListItem rli = element as RadioListItem;
rli.Key = this.itemIndex;
rli.Value = item.ToString();
}
this.itemIndex++;
base.PrepareContainerForItemOverride(element, item);
}
If the element is equal to item, this means that you have set the ItemsSource to a collection of RadioListItems. Else, you set the Value property of the RadioListItem control. This property is used when displaying each item.
Well, we are almost ready with our control. Now we have to specify how each item in our control will be displayed. We will use the generic.xaml file to set this. Do not forget that of Silverlight 2 this file must be located in the themes folder! And here it is our item template:
<RadioButton IsChecked="{TemplateBinding IsSelected}" Margin="0,2,0,2" IsHitTestVisible="False">
<ContentPresenter Content="{TemplateBinding Value}" />
</RadioButton>
Usage
The usage of our control is very simple. You can use it like a ListBox, or any other ItemsControl. You set the ItemsSource and you can always check the SelectedItem property to get currently selected item. Pay attention that if you set the ItemsSource to a collection of objects, different from RadioListItems, than the SelectedItem will be of type an object from the collection, not a RadioListItem!
<ctrl:RadioList ItemsSource="{StaticResource ...}" />
Conclusion
This control is very helpful in many situations. You can use it free and modify it to fit your needs. You can see the online questionnaire demo or download the source.

References