How to Uncheck radio button in WPF (MVVM)

Personally when I want this behavior I use a ListBox with the Template overwritten to use RadioButtons.

It's the best control suited to do all of the following :

  • display a list of items
  • only one item can be selected at a time, so only one property maintained in data model
  • user can leave selected item as null, indicating no item is selected

My custom style for the ListBox removes the borders and background color, and draws each item using a RadioButton with the IsChecked bound to the ListBoxItem.IsSelected. Typically something like this :

<Style x:Key="RadioButtonListBoxStyle" TargetType="{x:Type ListBox}">
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Cycle" />
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="{x:Type ListBoxItem}" >
                <Setter Property="Margin" Value="2, 2, 2, 0" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border Background="Transparent">
                                <RadioButton
                                    Content="{TemplateBinding ContentPresenter.Content}" VerticalAlignment="Center"
                                    IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"/>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

And to display the RadioButtons themselves is usually something very simple, like this :

<ListBox ItemsSource="{Binding AvailableValues}"
         SelectedValue="{Binding SelectedValue}"
         Style="{StaticResource RadioButtonListBoxStyle}" />

I used for this Scenario some Eventhandlers

<RadioButton Checked="RB_Checked" Click="RB_Clicked"/>

In the Codebehind of the XAML:

Private JustChecked as Boolean

Private Sub RB_Checked(sender As Object, e As RoutedEventArgs)
    Dim s As RadioButton = sender
    ' Action on Check...
    JustChecked = True
End Sub

Private Sub RB_Clicked(sender As Object, e As RoutedEventArgs)
    If JustChecked Then
        JustChecked = False
        e.Handled = True
        Return
    End If
    Dim s As RadioButton = sender
    If s.IsChecked Then s.IsChecked = False        
End Sub

Or in C#

private bool JustChecked;
private void RB_Checked(object sender, RoutedEventArgs e)
{
    RadioButton s = sender;
    // Action on Check...
    JustChecked = true;
}

private void RB_Clicked(object sender, RoutedEventArgs e)
{
    if (JustChecked) {
        JustChecked = false;
        e.Handled = true;
        return;
    }
    RadioButton s = sender;
    if (s.IsChecked)
        s.IsChecked = false;
}

Click Event fires after Checked Event


Try this:

public class OptionalRadioButton : RadioButton
{
    #region bool IsOptional dependency property
    public static readonly DependencyProperty IsOptionalProperty = 
        DependencyProperty.Register(
            "IsOptional", 
            typeof(bool), 
            typeof(OptionalRadioButton), 
            new PropertyMetadata((bool)true,
                (obj, args) =>
                {
                    ((OptionalRadioButton)obj).OnIsOptionalChanged(args);
                }));
    public bool IsOptional
    {
        get
        {
            return (bool)GetValue(IsOptionalProperty);
        }
        set
        {
            SetValue(IsOptionalProperty, value);
        }
    }
    private void OnIsOptionalChanged(DependencyPropertyChangedEventArgs args)
    {
        // TODO: Add event handler if needed
    }
    #endregion

    protected override void OnClick()
    {
        bool? wasChecked = this.IsChecked;
        base.OnClick();
        if ( this.IsOptional && wasChecked == true )
            this.IsChecked = false;
    }
}