Search
Close this search box.

WPF RadioButtons and data binding

There is a well-known issue with WPF RadioButton controls with data binding: when a radio button is unchecked the data binding is not undone. For example, suppose you have the following two radio buttons in the same group linked to a the “IsSuccess” (of type bool?) attribute of an object:

        <RadioButton 
                Grid.Row="0"
                Grid.Column="0"
                GroupName="rbGroup"
                Margin="8,0,0,0"
                VerticalAlignment="Center"                
                Content="Success"
                x:Name="rbSuccess" 
                IsChecked="{Binding Path=IsSuccess, Mode=TwoWay, Converter={StaticResource nullableBooleanConverter}}" />
        <RadioButton 
                Grid.Row="0"
                Grid.Column="1"
                GroupName="rbGroup"
                Margin="8,0,0,0"
                VerticalAlignment="Center"
                Content="Failure"               
                x:Name="rbFailure" />

When you check the rbSuccess radio button, the IsSuccess field becomes “true”, but when you check on the rbFailure radio button (and thus uncheck the rbSuccess one), the IsSuccess field is still true!

The problem is discussed here. There are several solutions. This blog explains one (using a control template). Another popular one is to use a ListBox restyled as a radio button. However, this causes other problems such as being unable to scroll past the radiobuttons (they are really a listbox, so scrolling is done inside the list).

The solution I have found is to put each radio button in a different group and link their checked/unchecked values via the converter. Like this:

        <RadioButton 
                Grid.Row="1"
                Grid.Column="0"
                GroupName="rbGroupSuccess"
                Margin="8,0,0,0"
                VerticalAlignment="Center"                
                Content="Success"
                x:Name="rbSuccess" 
                IsChecked="{Binding Path=IsSuccess, Mode=TwoWay, Converter={StaticResource nullableBooleanConverter}, ConverterParameter=true}" />
        
        <RadioButton 
                Grid.Row="1"
                Grid.Column="1"
                GroupName="rbGroupFailure"
                Margin="8,0,0,0"
                VerticalAlignment="Center"
                Content="Failure"               
                x:Name="rbFailure"    
                IsChecked="{Binding Path=IsSuccess, Mode=TwoWay, Converter={StaticResource nullableBooleanConverter}, ConverterParameter=false}" />

And here is the converter:

    [ValueConversion(typeof(bool?), typeof(bool))]
    public class SuccessConverter : IValueConverter
    {
     public
      object Convert(object value, Type targetType, object parameter,
                     CultureInfo culture) {
        bool param = bool.Parse(parameter.ToString());
        if (value == null) {
          return false;
        } else {
          return !((bool)value ^ param);
        }
      }

     public
      object ConvertBack(object value, Type targetType, object parameter,
                         CultureInfo culture) {
        bool param = bool.Parse(parameter.ToString());
        return !((bool)value ^ param);
      }
    }

Notice the converter parameter. Its role is to make sure that I get opposite values for the two radio buttons (when one is true, the other is false).

value
(IsSuccess)
paramresult
RadioButton.IsChecked = !(value ^ param)
truetruetrue
falsetruefalse
truefalsefalse
falsefalsetrue

(^ is the XOR operator in C#)

Technorati Tags: WPF,RadioButton

This article is part of the GWB Archives. Original Author: Clara Bouza S Mante

Related Posts