Uncheck Radio Button in WPF
Introduction
Recently I found myself in need of uncheck my selected Radio Button in WPF (Windows Presentation Framework). Unfortunately Radio Button has an unchecked event but it doesn’t fire. I thought of implementing uncheck onClick event, but even in this case it always givesChecked valuetrue after clicking on Radio Button. I started searching for examples in internet, but didn’t find an appropriate way to achieve this. One way I thought of styling the Checkbox to look like a Radio Button, but doing so is also had few issues. Then I thought of extending the Radio Button and use Dependency Property to achieve the same. This article describes the implementation of the Radio Button that supports uncheck and the way you can use it in your own applications. You can find the full implementation ofRadioButtonExtensionclass in the attached demo.
Using the Code
Create a new WPF application in Visual Studio 2012. Then add a new class in your project and give a name asRadioButtonExtension. Inherit the class withRadioButton object so that we can extend its events. Now in the constructor ofRadioButtonExtension class initialize the events of radio buttons as shown Listing 1 below:
Listing 1 - RadioButtonExtension.cs – modified constructor and events
public class RadioButtonExtension : RadioButton { public RadioButtonExtension() { this.Checked += RadioButtonExtension_Checked; this.Click += RadioButtonExtension_Click; } void RadioButtonExtension_Click(object sender, System.Windows.RoutedEventArgs e) { } void RadioButtonExtension_Checked(object sender, System.Windows.RoutedEventArgs e) { } }
Now create a Dependency Property in RadioButtonExtension.cs in order to change the checked property of Radio Button as follows:
Listing 2 – Dependency Property
public bool? IsCheckedChanged { get { return (bool?)GetValue(IsCheckedChangedProperty); } set { SetValue(IsCheckedChangedProperty, value); } } // Using a DependencyProperty as the backing store for IsChanged. // This enables animation, styling, binding, etc... public static readonly DependencyProperty IsCheckedChangedProperty = DependencyProperty.Register("IsChanged", typeof(bool?), typeof(RadioButtonExtension), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, CheckedChanged)); public static void CheckedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((RadioButtonExtension)d).IsChecked = (bool)e.NewValue; }
Lastly create a static int property, WasChecked which will help us to know the previous status of Checkbox. I update the value of the WasChecked property in the Click and Checked event. I also update the dependency property IsCheckedChanged which will call CheckedChanged method on property change and assign the Checked value of Radio Button with the new value as shown in listing 3 below.
Listing 3 - Modifying WasChecked property and IsCheckedChanged dependency property
public static int WasChecked { get; set; } void RadioButtonExtension_Click(object sender, System.Windows.RoutedEventArgs e) { if (WasChecked > 0) { this.IsCheckedChanged = !this.IsCheckedChanged; } WasChecked = 1; } void RadioButtonExtension_Checked(object sender, System.Windows.RoutedEventArgs e) { this.IsCheckedChanged = true; WasChecked = 0; }
The way this works is that when RadioButton is checked, the Checked event is fired which sets WasChecked = 0 and IsCheckedChanged =true. Then Click event is fired where I set WasChecked = 1.
Similarly, when the RadioButton is clicked again it fires the Click event in which case it checks WasChecked > 0, so it sets the dependency property IsCheckedChanged = false. Which fires the event CheckedChanged which assigns the new value to the RadioButton.
The full source code of the RadioButtonExtension class is shown in listing 4 below:
Listing 4 – Full RadioButtonExtension class source code
using System.Windows; using System.Windows.Controls; namespace RadioButtonSam { public class RadioButtonExtension : RadioButton { public static int WasChecked { get; set; } public bool? IsCheckedChanged { get { return (bool?)GetValue(IsCheckedChangedProperty); } set { SetValue(IsCheckedChangedProperty, value); } } // Using a DependencyProperty as the backing store for IsChanged. //This enables animation, styling, binding, etc... public static readonly DependencyProperty IsCheckedChangedProperty = DependencyProperty.Register("IsChanged", typeof(bool?), typeof(RadioButtonExtension), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, CheckedChanged)); public static void CheckedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((RadioButtonExtension)d).IsChecked = (bool)e.NewValue; } public RadioButtonExtension() { this.Checked += new RoutedEventHandler(RadioButtonExtension_Checked); this.Click += RadioButtonExtension_Click; } void RadioButtonExtension_Click(object sender, System.Windows.RoutedEventArgs e) { if (WasChecked > 0) { this.IsCheckedChanged = !this.IsCheckedChanged; } WasChecked = 1; } void RadioButtonExtension_Checked(object sender, System.Windows.RoutedEventArgs e) { this.IsCheckedChanged = true; WasChecked = 0; } } }
To use this new RadioButtonExtension in your project, you can include it in your MainWindow.xaml as shown in listing 5 below:
Listing 5 – Using RadioButtonExtension in MainWindow.xaml
<Window x:Class="RadioButtonSam.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" xmlns:controls="clr-namespace:RadioButtonSam"> <StackPanel> <RadioButton x:Name="rdMyRadio" Checked="rdMyRadio_Checked_1" Unchecked="rdMyRadio_Unchecked_1" Content="My Radio Button" /> <controls:RadioButtonExtension Content="My Custom Radio Button" GroupName="GR1" /> <controls:RadioButtonExtension Content="My 2nd Custom Radio Button" GroupName="GR1" /> <controls:RadioButtonExtension Content="My 3rd Custom Radio Button" GroupName="GR2" /> </StackPanel> </Window>
Hope that this would help you in your projects which help me a lot.
Click here to download the source file.