WPF绑定Enum到RadioButton
将枚举型的数据类型绑定到单选按钮的IsChecked属性中,可以避免定义多个bool类型与之进行绑定,尤其是枚举类型较多时候,对bool对象的维护会更加复杂。
1、定义枚举类型及值转换器
internal enum Gender { [Description("男")] Male, [Description("女")] Female, [Description("未知")] Unknown }
[ValueConversion(typeof(Gender), typeof(bool?))] public class Gender2IsCheckedConverter : 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; } }
2、定义RadioButton控件,并进行绑定
<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:Gender2IsCheckedConverter 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="男" Style="{StaticResource MyRadioButton}" IsChecked="{Binding Gender, Converter={StaticResource GenderConverter}, ConverterParameter={x:Static models:Gender.Male}}"/> <RadioButton Content="女" Style="{StaticResource MyRadioButton}" IsChecked="{Binding Gender, Converter={StaticResource GenderConverter}, ConverterParameter={x:Static models:Gender.Female}}"/> <RadioButton Content="未知" Style="{StaticResource MyRadioButton}" IsChecked="{Binding Gender, Converter={StaticResource GenderConverter}, ConverterParameter={x:Static models:Gender.Unknown}}"/> </StackPanel> </Window>
3、在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)); } }
4、运行截图