MVVM: Binding radio buttons to a view model?
binding, c#, mvvm, radio-button, wpf
Solution
If you start with Jason's suggestion then the problem becomes a single bound selection from a list which translates very nicely to a `ListBox`. At that point it's trivial to apply styling to a `ListBox` control so that it shows up as a `RadioButton` list.
<ListBox ItemsSource="{Binding ...}" SelectedItem="{Binding ...}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<RadioButton Content="{TemplateBinding Content}"
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsSelected}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Problem
EDIT: Problem was fixed in .NET 4.0. I have been trying to bind a group of radio buttons to a view model using the `IsChecked` button. After reviewing other posts, it appears that the `IsChecked` property simply doesn't work. I have put together a short demo that reproduces the problem, which I have included below. Here is my question: Is there a straightforward and reliable way to bind radio buttons using MVVM? Thanks. Additional information: The `IsChecked` property doesn't work for two reasons: When a button is selected, the IsChecked properties of other buttons in the group don't get set to false. When a button is selected, its own IsChecked property does not get set after the first time the button is selected. I am guessing that the binding is getting trashed by WPF on the first click. Demo project: Here is the code and markup for a simple demo that reproduces the problem. Create a WPF project and replace the markup in Window1.xaml with the following: ``` <Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300" Loaded="Window_Loaded"> <StackPanel> <RadioButton Content="Button A" IsChecked="{Binding Path=ButtonAIsChecked, Mode=TwoWay}" /> <RadioButton Content="Button B" IsChecked="{Binding Path=ButtonBIsChecked, Mode=TwoWay}" /> </StackPanel> </Window> ``` Replace the code in Window1.xaml.cs with the following code (a hack), which sets the view model: ``` using System.Windows; namespace WpfApplication1 { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { public Window1() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { this.DataContext = new Window1ViewModel(); } } } ``` Now add the following code to the project as `Window1ViewModel.cs`: ``` using System.Windows; namespace WpfApplication1 { public class Window1ViewModel { private bool p_ButtonAIsChecked; /// <summary> /// Summary /// </summary> public bool ButtonAIsChecked { get { return p_ButtonAIsChecked; } set { p_ButtonAIsChecked = value; MessageBox.Show(string.Format("Button A is checked: {0}", value)); } } private bool p_ButtonBIsChecked; /// <summary> /// Summary /// </summary> public bool ButtonBIsChecked { get { return p_ButtonBIsChecked; } set { p_ButtonBIsChecked = value; MessageBox.Show(string.Format("Button B is checked: {0}", value)); } } } } ``` To reproduce the problem, run the app and click Button A. A message box will appear, saying that Button A's `IsChecked` property has been set to true. Now select Button B. Another message box will appear, saying that Button B's `IsChecked` property has been set to true, but there is no message box indicating that Button A's `IsChecked` property has been set to false--the property hasn't been changed. Now click Button A again. The button will be selected in the window, but no message box will appear--the `IsChecked` property has not been changed. Finally, click on Button B again--same result. The `IsChecked` property is not updated at all for either button after the button is first clicked.