Linking a enumeration type to the IsChecked property of a RadioButton can eliminate the need for multiple boolean bindings, especially when dealing with numerous enum types, which simplifies maintenance of boolean objects.
- Define the enum and value converter
internal enum Gender
{
[Description("Male")]
Male,
[Description("Female")]
Female,
[Description("Unknown")]
Unknown
}
[ValueConversion(typeof(Gender), typeof(bool?))]
public class GenderToIsCheckedConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType != typeof(bool?))
{
throw new InvalidOperationException("The target must be a bool");
}
if (value == null || parameter == null)
{
throw new ArgumentNullException();
}
if (!Enum.IsDefined(typeof(Gender), value))
{
throw new InvalidOperationException("The value must be a Gender");
}
if (!Enum.IsDefined(typeof(Gender), parameter))
{
throw new InvalidOperationException("The parameter must be a Gender");
}
return (Gender)value == (Gender)parameter;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType != typeof(Gender))
{
throw new InvalidOperationException("The target must be a Gender");
}
if (parameter == null || !Enum.IsDefined(typeof(Gender), parameter))
{
throw new InvalidOperationException("The parameter must be a Gender");
}
if (value is not bool isChecked)
{
throw new InvalidOperationException("The value must be a bool");
}
return isChecked ? (Gender)parameter : Binding.DoNothing;
}
}
- Define the RadioButton control and perform the binding
<Window x:Class="WpfDeveloping.Views.RadioSampleWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:valueConverters="clr-namespace:WpfDeveloping.ValueConverters"
xmlns:models="clr-namespace:WpfDeveloping.Models"
mc:Ignorable="d"
Title="RadioSampleWindow"
WindowStartupLocation="CenterScreen"
Height="180" Width="320">
<Window.Resources>
<valueConverters:GenderToIsCheckedConverter x:Key="GenderConverter"/>
<Style x:Key="MyRadioButton" TargetType="RadioButton">
<Setter Property="Height" Value="30"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Margin" Value="10,0,0,0"/>
</Style>
</Window.Resources>
<StackPanel Orientation="Vertical">
<RadioButton Content="Male" Style="{StaticResource MyRadioButton}"
IsChecked="{Binding Gender, Converter={StaticResource GenderConverter}, ConverterParameter={x:Static models:Gender.Male}}"/>
<RadioButton Content="Female" Style="{StaticResource MyRadioButton}"
IsChecked="{Binding Gender, Converter={StaticResource GenderConverter}, ConverterParameter={x:Static models:Gender.Female}}"/>
<RadioButton Content="Unknown" Style="{StaticResource MyRadioButton}"
IsChecked="{Binding Gender, Converter={StaticResource GenderConverter}, ConverterParameter={x:Static models:Gender.Unknown}}"/>
</StackPanel>
</Window>
- Define the enum object in the ViewModel
internal class RadioSampleWindowViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Gender Gender
{
get => _gender;
set
{
if (_gender != value)
{
_gender = value;
OnPropertyChanged();
Debug.WriteLine($"Current gender: {value}");
}
}
}
private Gender _gender = Gender.Unknown;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
- Screenshot of the application