如何将RadioButtons绑定到一个枚举?

我有这样的枚举:

public enum MyLovelyEnum { FirstSelection, TheOtherSelection, YetAnotherOne }; 

我在我的DataContext中有一个属性:

 public MyLovelyEnum VeryLovelyEnum { get; set; } 

我的WPF客户端中有三个RadioButton。

 <RadioButton Margin="3">First Selection</RadioButton> <RadioButton Margin="3">The Other Selection</RadioButton> <RadioButton Margin="3">Yet Another one</RadioButton> 

现在我该如何将RadioButtons绑定到该属性以进行正确的双向绑定?

你可以使用更通用的转换器

 public class EnumBooleanConverter : IValueConverter { #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string parameterString = parameter as string; if (parameterString == null) return DependencyProperty.UnsetValue; if (Enum.IsDefined(value.GetType(), value) == false) return DependencyProperty.UnsetValue; object parameterValue = Enum.Parse(value.GetType(), parameterString); return parameterValue.Equals(value); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string parameterString = parameter as string; if (parameterString == null) return DependencyProperty.UnsetValue; return Enum.Parse(targetType, parameterString); } #endregion } 

在您使用的XAML-Part中:

 <Grid> <Grid.Resources> <l:EnumBooleanConverter x:Key="enumBooleanConverter" /> </Grid.Resources> <StackPanel > <RadioButton IsChecked="{Binding Path=VeryLovelyEnum, Converter={StaticResource enumBooleanConverter}, ConverterParameter=FirstSelection}">first selection</RadioButton> <RadioButton IsChecked="{Binding Path=VeryLovelyEnum, Converter={StaticResource enumBooleanConverter}, ConverterParameter=TheOtherSelection}">the other selection</RadioButton> <RadioButton IsChecked="{Binding Path=VeryLovelyEnum, Converter={StaticResource enumBooleanConverter}, ConverterParameter=YetAnotherOne}">yet another one</RadioButton> </StackPanel> </Grid> 

您可以进一步简化接受的答案。 而不是在xaml中input枚举string,并在转换器中进行更多的工作,而不是使用string表示forms。而CrimsonX评论道,在编译时抛出错误,而不是运行时:

ConverterParameter = {x:静态本地:YourEnumType.Enum1}

 <StackPanel> <StackPanel.Resources> <local:EnumToBooleanConverter x:Key="EnumToBooleanConverter" /> </StackPanel.Resources> <RadioButton IsChecked="{Binding Path=YourEnumProperty, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static local:YourEnumType.Enum1}}" /> <RadioButton IsChecked="{Binding Path=YourEnumProperty, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static local:YourEnumType.Enum2}}" /> </StackPanel> 

然后简化转换器:

 public class EnumToBooleanConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value.Equals(parameter); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value.Equals(true) ? parameter : Binding.DoNothing; } } 

注 – 在同一个容器中的多个RadioButton组(11年2月17日):

在xaml中,如果单选button共享同一个父容器,则select其中一个将取消select该容器中的所有其他容器(即使它们绑定到不同的属性)。 因此,尽量保持你的RadioButton的绑定到一个共同的属性组合在他们自己的容器像堆栈面板。 在您的相关RadioButtons不能共享一个父容器的情况下,然后将每个RadioButton的GroupName属性设置为一个公共值,以便对它们进行逻辑分组。

注 – 嵌套在类中的枚举types(11年4月28日):

如果枚举types嵌套在类中(而不是直接嵌套在名称空间中),则可能可以使用“+”语法来访问XAML中的枚举,如(无标记的)对无法find的问题的回答中所述WPF中静态引用的枚举types :

ConverterParameter = {x:静态本地: YourClass + YourNestedEnumType.Enum1}

但是,由于此Microsoft连接问题 ,VS2010中的devise器将不再加载说明"Type 'local:YourClass+YourNestedEnumType' was not found." ,但项目编译并运行成功。 当然,如果可以直接将枚举types移动到名称空间,则可以避免此问题。

编辑(十二月16 '10):

感谢匿名提示返回Binding.DoNothing而不是DependencyProperty.UnsetValue。

编辑(4月5 '11):

简化的ConvertBack的if-else使用三元运算符。

编辑(1月27 '12):

如果使用枚举标志,转换器将如下所示:

 public class EnumToBooleanConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return ((Enum)value).HasFlag((Enum)parameter); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value.Equals(true) ? parameter : Binding.DoNothing; } } 

编辑(15年5月7日):

在Numlable Enum的情况下(在问题中没有被问到,但在某些情况下可能需要,例如ORM从DB返回null,或者只要在程序逻辑中没有提供值就可以),请记得添加在转换方法中初始空检查并返回适当的布尔值,通常是false(如果你不想要任何单选button),如下所示:

  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value == null) { return false; // or return parameter.Equals(YourEnumType.SomeDefaultValue); } return value.Equals(parameter); } 

对于EnumToBooleanConverter答案:而不是返回DependencyProperty.UnsetValue考虑返回Binding.DoNothing单选buttonIsChecked值变为false的情况下。 前者表示一个问题(可能会向用户显示一个红色的矩形或类似的validation指标),而后者则表明不应该做任何事情,这就是在这种情况下所要做的。

http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.convertback.aspx http://msdn.microsoft.com/en-us/library/system.windows.data.binding .donothing.aspx

我将使用ListBox中的RadioButtons,然后绑定到SelectedValue。

这是一个关于这个主题的旧线程,但基本思路应该是一样的: http : //social.msdn.microsoft.com/Forums/en-US/wpf/thread/323d067a-efef-4c9f-8d99-fecf45522395/

通过将单选button绑定到任何types(枚举,布尔,string,整数等)的能力,扩展了以上伟大的想法,并提供了工作示例代码:

http://www.codeproject.com/Tips/720497/Binding-Radio-Buttons-to-a-Single-Property

对于UWP来说,并不是那么简单:你必须跳过一个额外的箍来传递一个字段值作为参数。

例1

对于WPF和UWP都有效。

 <MyControl> <MyControl.MyProperty> <Binding Converter="{StaticResource EnumToBooleanConverter}" Path="AnotherProperty"> <Binding.ConverterParameter> <MyLibrary:MyEnum>Field</MyLibrary:MyEnum> </Binding.ConverterParameter> </MyControl> </MyControl.MyProperty> </MyControl> 

例2

对于WPF和UWP都有效。

 ... <MyLibrary:MyEnum x:Key="MyEnumField">Field</MyLibrary:MyEnum> ... <MyControl MyProperty="{Binding AnotherProperty, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={StaticResource MyEnumField}}"/> 

例3

仅适用于WPF!

 <MyControl MyProperty="{Binding AnotherProperty, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static MyLibrary:MyEnum.Field}}"/> 

UWP不支持x:Static因此示例3是不可能的; 假设你去例1 ,结果是更详细的代码。 例2略好,但仍不理想。

 public abstract class EnumToBooleanConverter<TEnum> : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { var Parameter = parameter as string; if (Parameter == null) return DependencyProperty.UnsetValue; if (Enum.IsDefined(typeof(TEnum), value) == false) return DependencyProperty.UnsetValue; return Enum.Parse(typeof(TEnum), Parameter).Equals(value); } public object ConvertBack(object value, Type targetType, object parameter, string language) { var Parameter = parameter as string; return Parameter == null ? DependencyProperty.UnsetValue : Enum.Parse(typeof(TEnum), Parameter); } } 

然后,对于您希望支持的每种types,请定义一个转换器来将枚举types框起来。

 public class MyEnumToBooleanConverter : EnumToBooleanConverter<MyEnum> { //Nothing to do! } 

必须装盒的原因是因为似乎没有办法在ConvertBack方法中引用types; 拳击照顾。 如果使用前两个示例中的任何一个,则只需引用参数types即可,无需从盒装类inheritance。 如果你希望以一行的方式完成所有工作,并且可能性最小,那么后一种解决scheme是理想的。

用法类似于示例2 ,但事实上不太详细。

 <MyControl MyProperty="{Binding AnotherProperty, Converter={StaticResource MyEnumToBooleanConverter}, ConverterParameter=Field}"/> 

缺点是你必须为你想支持的每种types定义一个转换器。

基于Scott的EnumToBooleanConverter。 我注意到ConvertBack方法不能用Enum和flags代码工作。

我试过下面的代码:

 public class EnumHasFlagToBooleanConverter : IValueConverter { private object _obj; public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { _obj = value; return ((Enum)value).HasFlag((Enum)parameter); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value.Equals(true)) { if (((Enum)_obj).HasFlag((Enum)parameter)) { // Do nothing return Binding.DoNothing; } else { int i = (int)_obj; int ii = (int)parameter; int newInt = i+ii; return (NavigationProjectDates)newInt; } } else { if (((Enum)_obj).HasFlag((Enum)parameter)) { int i = (int)_obj; int ii = (int)parameter; int newInt = i-ii; return (NavigationProjectDates)newInt; } else { // do nothing return Binding.DoNothing; } } } } 

我唯一不能工作的是从inttargetType进行targetType所以我将其硬编码为NavigationProjectDates (我使用的枚举)。 而且, targetType == NavigationProjectDates


编辑更多通用标志枚举转换器:

    公共类FlagsEnumToBooleanConverter:IValueConverter {
         private int _flags = 0;
        公共对象Convert(对象值,typestargetType,对象参数,string语言){
             if(value == null)返回false;
             _flags =(int)值;
            typest = value.GetType();
             object o = Enum.ToObject(t,parameter);
            返回((Enum)值).HasFlag((Enum)o);
         }

        公共对象ConvertBack(对象值,typestargetType,对象参数,string语言)
         {
             if(value?.Equals(true)?? false){
                 _flags = _flags |  (int)参数;
             }
             else {
                 _flags = _flags&〜(int)参数;
             }
             return _flags;
         }
     }