如何将RadioButtons绑定到枚举?

浪子不回头ぞ 提交于 2020-02-26 13:58:11

我有一个像这样的枚举:

public enum MyLovelyEnum
{
    FirstSelection,
    TheOtherSelection,
    YetAnotherOne
};

我在DataContext中获得了一个属性:

public MyLovelyEnum VeryLovelyEnum { get; set; }

我在WPF客户端中得到了三个RadioButtons。

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

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


#1楼

基于Scott的EnumToBooleanConverter。 我注意到ConvertBack方法在带有标志代码的Enum上不起作用。

我尝试了以下代码:

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因此我将其硬编码为我使用的枚举NavigationProjectDates 。 而且, targetType == NavigationProjectDates ...


编辑以获得更多通用的Flags Enum转换器:

public class FlagsEnumToBooleanConverter : IValueConverter {
        private int _flags=0;
        public object Convert(object value, Type targetType, object parameter, string language) {
            if (value == null) return false;
            _flags = (int) value;
            Type t = value.GetType();
            object o = Enum.ToObject(t, parameter);
            return ((Enum)value).HasFlag((Enum)o);
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            if (value?.Equals(true) ?? false) {
                _flags = _flags | (int) parameter;
            }
            else {
                _flags = _flags & ~(int) parameter;
            }
            return _flags;
        }
    }

#2楼

您可以进一步简化接受的答案。 您可以显式传入枚举值而不是字符串表示形式,而不必在xaml中将枚举形式作为字符串在xaml中键入,并且在转换器中完成不必要的工作,而正如CrimsonX所评论的那样,错误是在编译时而不是在运行时抛出的:

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

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

然后简化转换器:

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<Boolean>似乎是一个合理的解决方案。

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

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

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

如果您的枚举类型嵌套在一个类(而不是直接在命名空间),如在(未标示)回答说这个问题你也许可以用“+”语法来访问XAML枚举 无法找到WPF中静态引用的枚举类型

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

编辑(2010年12月16日):

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

编辑(11年5月5日):

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

编辑(2012年1月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; } }

编辑(15年5月7日):

如果为Nullable枚举(问题中 要求,但在某些情况下可能需要,例如ORM从数据库返回null或在程序逻辑中没有提供该值的任何时候),请记住添加在Convert方法中进行初始空检查并返回适当的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); }

#3楼

对于EnumToBooleanConverter答案:对于单选按钮IsChecked值变为false的情况,考虑返回Binding.DoNothing而不是返回DependencyProperty.UnsetValue。 前者表明存在问题(可能会向用户显示一个红色矩形或类似的验证指示符),而后者仅表明不应采取任何措施,这是这种情况下所需要的。

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楼

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

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


#5楼

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

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>
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!