当前位置:  开发笔记 > 运维 > 正文

如何将RadioButtons绑定到枚举?

如何解决《如何将RadioButtons绑定到枚举?》经验,为你挑选了4个好方法。

我有这样的枚举:

public enum MyLovelyEnum
{
    FirstSelection,
    TheOtherSelection,
    YetAnotherOne
};

我的DataContext中有一个属性:

public MyLovelyEnum VeryLovelyEnum { get; set; }

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

First Selection
The Other Selection
Yet Another one

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



1> Scott..:

您可以进一步简化已接受的答案.您可以显式传入枚举值而不是字符串表示形式,而不是在xaml中将枚举输入为xaml中的字符串并在转换器中执行更多工作,而在CrimsonX注释时,错误会在编译时而不是运行时抛出:

ConverterParameter = {x:Static local:YourEnumType.Enum1}


              
                  
    
    
    

然后简化转换器:

public class ComparisonConverter : 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) == true ? parameter : Binding.DoNothing;
    }
}

注 - NullReferenceException(18年10月10日):

更新了示例以消除抛出NullReferenceException的可能性.IsChecked是一个可空类型,所以返回Nullable似乎是一个合理的解决方案.

注意 - 同一个容器中的多组RadioButton(2011年2月17日):

在xaml中,如果单选按钮共享同一个父容器,则选择一个将取消选择该容器中的所有其他容器(即使它们绑定到不同的属性).因此,请尝试将绑定到公共属性的RadioButton保存在自己的容器中,就像堆栈面板一样.如果您的相关RadioButton不能共享单个父容器,则将每个RadioButton的GroupName属性设置为公共值以对它们进行逻辑分组.

注 - 嵌套在类中的枚举类型(2011年4月28日):

如果您的枚举类型嵌套在类中(而不是直接在命名空间中),您可以使用"+"语法来访问XAML中的枚举,如(无标记)问题的答案中所述无法找到WPF中静态引用的枚举类型:

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

但是,由于此Microsoft Connect问题,VS2010中的设计器将不再加载说明"Type 'local:YourClass+YourNestedEnumType' was not found.",但该项目确实可以成功编译和运行.当然,如果能够直接将枚举类型移动到命名空间,则可以避免此问题.

编辑(2010年12月16日):

感谢anon建议返回Binding.DoNothing而不是DependencyProperty.UnsetValue.

编辑(2011年4月5日):

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

编辑(12月27日):

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

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;
    }
}

编辑(2015年5月7日):

在Nullable Enum的情况下(在问题中没有问到,但在某些情况下可能需要,例如ORM从DB返回null或者在程序逻辑中没有提供值的情况下可能有意义),记得添加转换方法中的初始null检查并返回相应的bool值,通常为false(如果您不想选择任何单选按钮),如下所示:

    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);
    }



我同意,我相信这是一个更好的解决方案.此外,如果更改枚举值,使用此转换将导致项目在编译时而不是运行时中断,这是一个很大的优势.
好的解决方案 我想补充一点,这只是一个比较2个值的比较转换器.它可以具有比EnumToBooleanConverter更通用的名称,例如ComparisonConverter
@斯科特,非常好.在任何情况下,无论有没有Flags属性,此转换器都很好.但是在大多数情况下将这个过滤器直接用作带有枚举的转换器作为标志将是愚蠢的.原因是您应该使用先前的值来实现布尔计算(| =或^ =)以获得正确的结果,但转换器无法访问先前的值.然后,您应该为每个枚举值添加一个bool,并在MVVM模型中自己执行适当的布尔值计算.但感谢每一个信息,非常有用.
这肯定是一个比被接受的解决方案更好的解决方案.+1
更简单的解决方案,我喜欢它并且运行良好.
在Windows Phone 8中(可能是Win Store应用程序)我们没有x:static,所以我们不能直接在这里使用解决方案.然而,IDE/Complier足够聪明,并且针对所有字符串文字查找字符串(无论如何我猜).例如,这工作在设计/编译时而不是运行时,将捕获Driving中的任何拼写错误.

2> Lars..:

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

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中你使用:


    
      
    
    
      first selection
      the other selection
      yet another one
    


对我来说就像一个魅力.作为补充,我修改了ConvertBack也将UnsetValue返回到"false",因为silverlight(可能是WPF)调用转换器两次 - 一次取消设置旧的单选按钮值并再次设置新的单选按钮值.我把其他东西挂在了物业安装者身上,所以我只想叫它一次. - if(parameterString == null || value.Equals(false))返回DependencyProperty.UnsetValue;
对此解决方案的绑定仅在单向上正常工作.我无法通过将绑定属性分配给不同的值来以编程方式切换radiobutton.如果您想要一个正确的工作和更好的解决方案,请使用scott的方法.
据我所知,除非单选按钮位于不同的组中,否则必须执行此*(并且默认情况下,同一组中没有设置具有相同父级的GroupName的AFAIK按钮).否则,调用设置属性"反弹"并导致奇怪的行为.
是的,但是如果在设置为false时在转换器中调用Unset,那么它不是真正的EnumToBooleanConverter,而是更多的EnumToRadioButtonConverter.所以我检查我的属性setter中的值是否不同:if(_myEnumBackingField == value)return;
重复上述说明:这不是两种方式.您无法设置属性并使radiobutton正确更改其IsChecked.你真的想要使用Scott的下面的方法.

3> 小智..:

对于EnumToBooleanConverter答案:在没有返回DependencyProperty.UnsetValue的情况下,考虑在单选按钮IsChecked值变为false的情况下返回Binding.DoNothing.前者表示存在问题(并且可能向用户显示红色矩形或类似的验证指示符),而后者仅表示不应该执行任何操作,这是在这种情况下需要的.

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



4> Martin Moser..:

我将在ListBox中使用RadioButtons,然后绑定到SelectedValue.

这是关于这个主题的旧帖子,但基本思想应该是相同的:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/323d067a-efef-4c9f-8d99-fecf45522395/


这是迄今为止最好的解决方案,其他一切都会导致冗余代码.([另一个例子](http://stackoverflow.com/a/9145914/546730)使用ListBox)
推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有