Jul
08

WPF RadioButton Binding to IsChecked Property

posted on 08 July 2010 in programming

Warning: Please consider that this post is over 13 years old and the content may no longer be relevant.

I wasted a few development hours discovering this strange behaviour when binding to the IsChecked property of a RadioButton in WPF when using MVVM. You can read about the issue on the MSDN forum, but from my experience if you have a two way binding on the is IsChecked property of a RadioButton which is part of a group, then after you set the bound property in code a couple of times, the RadioButton loses it’s binding all together.

Here is my original code that kept losing it’s binding:

<ItemsControl ItemsSource="{Binding Elements}" Margin="0,10,0,10">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <RadioButton Content="{Binding Key}"
        GroupName="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.Title}"
        IsChecked="{Binding Path=IsSelected}"
        Margin="0,5,0,5"/>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

There a couple of ways to solve this,

  • You can subclass the RadioButton
  • You could use OneWay binding on IsChecked to set the RadioButton state from code, then bind the Command property to a  Command when user clicks on the RadioButton.
<ItemsControl ItemsSource="{Binding Elements}" Margin="0,10,0,10">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <RadioButton Content="{Binding Key}"
        GroupName="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.Title}"
        IsChecked="{Binding Path=IsSelected, Mode=OneWay}"
        Command="{Binding IsSelectedCommand}"
        CommandParameter="{Binding}"
        Margin="0,5,0,5"/>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>
  • My preferred option: (as suggested by karliwatson) use a ListBox for the grouping and bind the ListBoxItem’s IsSelected property to your ViewModel, then bind the RadioButton’s IsChecked property to the list box item’s IsSelected property. Don’t set a group on the RadioButton.
<ListBox ItemsSource="{Binding Elements}" Margin="0,10,0,10" BorderThickness="0" Background="Transparent">
  <ListBox.ItemContainerStyle>
    <Style TargetType="{x:Type ListBoxItem}">
      <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="ListBoxItem">
            <ContentPresenter/>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </ListBox.ItemContainerStyle>
  <ListBox.ItemTemplate>
    <DataTemplate>
        <RadioButton Content="{Binding Key}"
            IsChecked="{Binding Path=IsSelected, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"
            Margin="0,5,0,5"/>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>