RadioButton unchecked bindings issue still not resolved?
- I recently noticed that when I bind a RadioButton to a bool, that bool is set when the RadioButton is checked but never unset when it's unchecked. After reading the following post:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1429712&SiteID=1
I noticed that furthermore the bindings are totally dropped after a few clicks between two RadioButtons. Surely this is a bug, does anyone have an update on it's status? Binding to RadioButtons is such a common thing that I'd have to image it's been addressed by now.
Thanks!
Answers
- I can further confirm that the bindings are lost by attempting to do things with UpdateSourceTrigger=Explicit and handling the checked and unchecked events. When the RadioButton is checked for the first time I can get a BindingExpression for RadioButton.IsCheckedProperty and call UpdateSource. However, when I pick a different RadioButton and the uncheck event fires I try to do the same thing and the BindingExpression for RadioButton.IsCheckedProperty is gone. I can't find a workaround other than to forgo data binding with RadioButtons.
This is a known bug, with no known workaround.
Sadly, the situation is more complex than you might think. When you click one button, the other buttons in the group are supposed to clear. How can RadioButton do this? If it calls SetValue(IsClicked, false), it sets a local value and hides the value provided by a style or template. If it calls ClearValue(IsClicked) it removes the binding. The first approach breaks one set of apps, the second breaks a different set of apps. Someone is always unhappy.
All Replies
- I can further confirm that the bindings are lost by attempting to do things with UpdateSourceTrigger=Explicit and handling the checked and unchecked events. When the RadioButton is checked for the first time I can get a BindingExpression for RadioButton.IsCheckedProperty and call UpdateSource. However, when I pick a different RadioButton and the uncheck event fires I try to do the same thing and the BindingExpression for RadioButton.IsCheckedProperty is gone. I can't find a workaround other than to forgo data binding with RadioButtons.
This is a known bug, with no known workaround.
Sadly, the situation is more complex than you might think. When you click one button, the other buttons in the group are supposed to clear. How can RadioButton do this? If it calls SetValue(IsClicked, false), it sets a local value and hides the value provided by a style or template. If it calls ClearValue(IsClicked) it removes the binding. The first approach breaks one set of apps, the second breaks a different set of apps. Someone is always unhappy.
- IMO the issue would best be resolved by having a group of radio buttons behave in the way most people would assume they do.
To be more explicit - if you have TwoWay bindings on a group of RadioButtons they would remain in place as long as the RadioButtons were in existance. When the value of IsChecked changes for any RadioButton the associated binding would record the change.
In my own coding I cannot think of a scenario where I would want WPF to remove a RadioButton binding automatically. I think Styles/Templates that are "looking at" IsChecked would be referencing it via a comparison in a Trigger or if the developer is explicitly setting it then he's unlikely to be binding it to it ALSO.
Said differently, if you code up an application where you trample on your own bindings via a Style or Template, then that's either your error or intention.
I'm not sure what I'm missing but this issue seems simple to me.
If the RadioButton has a binding expression, I don't think WPF should remove it period.
I find the current behavior makes a RadioButton group much harder to use than necessary. I'm forced to listen to a Click event on each button and do the "right" thing.
Can this issue be addressed in the .NET 3.5 release?
Would you mind providing examples to better illustrate the complexity you refer to? I understand how using ClearValue instead SetValue would cause the problem described in this thread, but I can't think of a case where ClearValue should be called automatically. Please elaborate.
Thanks. I completely agree with Richie and would also like to see an example illustrating the complexity Sam mentioned. I'm planning to handle binding to the radio button manually through listening to Checked / Unchecked but I also plan to have a trigger listening for the Checked value to change that would cause some data styling. Thanks for setting things straight Sam!
When you click a RadioButton, the internal code has to do something to clear the other buttons in the group. Once upon a time it used to call SetValue(false), but someone complained because their app relied on values and triggers defined in a style - setting a local value hid this completely. So it got "fixed" by calling ClearValue instead. This broke apps like yours that use data binding on IsChecked. No one realized this until fairly recently.
I totally agree that the internal code should not trample your bindings. The "fix" we shipped needs to be improved to take this case into account. It's probably too late for WPF 3.5, but this should certainly be addressed for the next release after that.
Hi Sam,
Thanks for clarifying how the situation came to be the way it is. It's great to hear you guys want to improve the "fix".
If it can't make it into 3.5, hopefully that means RTM is just around the corner

Thanks.
I've resorted to defining a PageLoaded method that caches the Binding objects of each RadioButton in Page.Resources. Then I have a handler for the Unchecked event, which checks the status of the bindings and restores them if necessary. Not what I really want to be doing, but it "works".
- I ran into this one today and have an alternative solution that you can use in certain circumstances.
If your radio buttons are in a list, horizontal or vertical, you can use a ListBox with a style that maps the IsSelected property of a ListBoxItem to the IsChecked property of its items.
In my tests this appears to preserve the bindings you use and everything works as expected. I've included code below for a vertical list box style and test list in case you decide to go with this strategy!<Style x:Key="VerticalRadioButtonListStyle" TargetType="ListBox"> <Style.Resources> <Style TargetType="ListBoxItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListBoxItem"> <Grid Margin="2"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <RadioButton IsChecked="{Binding IsSelected, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" /> <ContentPresenter Grid.Column="1" Margin="2,0,0,0" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </Style.Resources> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <WrapPanel Orientation="Vertical" /> </ItemsPanelTemplate> </Setter.Value> </Setter> <Setter Property="BorderThickness" Value="0" /> <Setter Property="Background" Value="Transparent" /> </Style>
...<ListBox Name="ReportingLevelRadioButtonList" Style="{StaticResource VerticalRadioButtonListStyle}" Grid.Column="1"> <ListBox.Items> <ListBoxItem IsSelected="{Binding ...}">Option 1</ListBoxItem> <ListBoxItem IsSelected="{Binding ...}">Option 2</ListBoxItem> <ListBoxItem IsSelected="{Binding ...}">Option 3</ListBoxItem> </ListBox.Items> </ListBox> - I've been able to workaround this issue by explicitly putting my RadioButtons in separate groups:
<RadioButton GroupName="Apples" IsChecked="{Binding Path=IsApples}" Content="Apples" /> <RadioButton GroupName="Oranges" IsChecked="{Binding Path=IsOranges}" Content="Oranges" /> - Proposed As Answer bypooranlive Tuesday, October 20, 2009 5:11 AM
- Edited byBruno Martinez Friday, September 05, 2008 2:18 PMFormatting
- Why not bind to a bool like this?
in the BO:
private bool _MyBool;
public bool MyBool
{
get { return _MyBool; }
set { _MyBool = value; OnPropertyChanged("MyBool"); } //INotifyPropertyChanged Interface
}
Xaml:
<RadioButton GroupName="someGroup" IsChecked="{Binding Path=MyBool, Converter={StaticResource ConvertToOppositeBool}}">False</RadioButton>
<RadioButton GroupName="someGroup" IsChecked="{Binding Path=MyBool}">True</RadioButton>
Does the trick for me.
Greets,
Arne
- Edited byArneWauters Monday, September 15, 2008 10:04 AM
- I did try something similar to that as well, but the issue of the binding being suddenly dropped was still there. It looks like styling the button group as a ListBox is really the only way to go to avoid that for the moment.
What can also be very useful is to have the buttons in the group bound to an integer dependency, rather than a boolean. The following code is similar to what I used (similar to karliwatson's):
<
Style x:Key="RadioButtonGroupStyle" TargetType="{x:Type ListBox}">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<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 TargetType="{x:Type ListBoxItem}">
<Border Background="Transparent">
<RadioButton IsHitTestVisible="False" Focusable="False" IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}" Content="{TemplateBinding Content}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
...
<
GroupBox>
<ListBox Name="MySelector" Style="{StaticResource RadioButtonGroupStyle}" Grid.Row="0">
<ListBox.Items>
<ListBoxItem Name="Item0" >Option 0</ListBoxItem>
<ListBoxItem Name="Item1">Option 1</ListBoxItem>
<ListBoxItem Name="Item2">Option 2</ListBoxItem>
</ListBox.Items>
<ListBox.SelectedIndex>
<Binding Path="MyIntProperty" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
</ListBox.SelectedIndex>
</ListBox>
</GroupBox>
alternatively, you could use ItemsSource bound to an enum (optionally filtered via a System.Windows.Data.CollectionViewSource):
<
GroupBox>
<ListBox Name="MySelector" Style="{StaticResource RadioButtonGroupStyle}" ItemsSource="{Binding Source={StaticResource MyFilteredCollectionViewSource}}">
<ListBox.SelectedItem>
<Binding Source="{StaticResource mydata}" Path="MyEnumProperty" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
</ListBox.SelectedItem>
</ListBox>
</GroupBox>- Edited byDave Gallagher Monday, September 15, 2008 4:43 PM
- Edited byDave Gallagher Monday, September 15, 2008 4:41 PM
- I hit that problem too and found it a real nuisance.I tried to get rid of the GroupName as some post suggested to no avail.I tried to force an update of the binding by code but I hit an exception as I guess the framework removes the binding so the BindingExpression becomes null...I finally used the Checked event on each radio to call a generic update routine:private void myRadio_Checked(object sender, RoutedEventArgs e){updateRadio(sender);}void updateRadio(object sender){//find the radioRadioButton rd= (RadioButton)sender;//I used the Tag property of the radio to store the name of the property I want to updatestring s = rd.Tag.ToString();//retrieve the object containing the properties to updateWizardData data = (WizardData)this.DataContext;//call a generic invoke function to set the propertiesInvokeTypeMember<WizardData>(data, s, new object[1] { true } );}using System.Reflection;//InvokeMember allows you to set a property once you know its namepublic static void InvokeTypeMember<T>(object obj, string prop, object[] arg){Type myType = obj.GetType();myType.InvokeMember(prop, BindingFlags.SetProperty, null, obj, arg);}I always set the value to true once the radio is clicked.In the WizardData object where my properties live, I have an extra function to set all the properties to false which is called by each property related to the radio on the set:void clearProps(){WizardSettings.Default.page4_Option1 = false;WizardSettings.Default.page4_Option2 = false;...}public bool Option1{get { return WizardSettings.Default.page4_Option1; }set { clearProps(); WizardSettings.Default.page4_Option1 = value; }The only thing I got left to do at this point is to check that at least one property is true when loading the page and set the UI accordingly.This will be done using the property returned byobject val = (object)myType.InvokeMember(prop, BindingFlags.GetProperty, null, obj, null);which will be called repetitively for all the radios to check if val is true.Still this is a lot of code to work around the bug or... have I got something wrong in the first place and can this be simplified?ThanksPasx
- In addition to my post above.I finally found it easier to rely on a one way binding to update the relation b/w the source properties and the radio buttons.The binding works fine this way so on loading the page the appropriate radio button is checked without additional code behind.the xaml now looks like:<RadioButton Name="rdOption1" Tag="page4_Option1"IsChecked="{Binding Path=page4_Option1, Mode=OneWay}"Checked="myRadio_Checked">Option1</RadioButton>Pasx
- Thanks for the tip. I process each of two RadioButtons separately so putting them in separate groups is exactly what I needed to do.
- I have the same problem and I tried the ListBox styling work-around
The problem is that when compiled in VS the xaml shows an error with setting the Content property
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border Background="Transparent">
<RadioButton IsHitTestVisible="False" Focusable="False" IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}" Content="{TemplateBinding Content}"/>
</Border>
</ControlTemplate>
When I remove the Content property things work fine (including events and binding), but there is no text next to the radio button.
I tried changing the code to:
<ControlTemplate>
<Border Background="Transparent">
<StackPanel Orientation="Horizontal">
<ContentControl Content="{TemplateBinding Content}"/>
<RadioButton IsHitTestVisible="False" Focusable="False" IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"/>
</StackPanel>
</Border>
</ControlTemplate>
This code has a compile error "Cannot find the static member 'ContentProperty' on the type 'Control'"
I'm using .NET 3.5 sp1 and RadioButton binding still doesn't work
Sten - The original problem has been fixed for WPF 4.0. I'm still not aware of a completely satisfactory workaround in 3.x.
Dev Lead, Windows Presentation Foundation, WinFX - That is awesome news - thanks Sam!
- I've found that this solutions works like a charm: http://pstaev.blogspot.com/2008/10/binding-ischecked-property-of.html . Thanks to Peter Staev.


