转换器显示枚举的描述,并在从wpf的combobox中选择项目时转换回枚举值

我正在使用枚举来在我的combobox中登记值。 我想写一个转换器,它将显示所选枚举值的“描述”。 并且,选中后,它将返回枚举值。

大多数在线转换器都没有实现ConvertBack()方法(这就是我在这里发布的原因)。

提前致谢。

这是ConvertBack方法:

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value; } 

完整转换器代码:

 public class EnumConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value == null) return DependencyProperty.UnsetValue; return GetDescription((Enum)value); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value; } public static string GetDescription(Enum en) { Type type = en.GetType(); MemberInfo[] memInfo = type.GetMember(en.ToString()); if (memInfo != null && memInfo.Length > 0) { object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); if (attrs != null && attrs.Length > 0) { return ((DescriptionAttribute)attrs[0]).Description; } } return en.ToString(); } } 

编辑

这是我的ComboBox XAML:

        

编辑2:

我最初有一个不正确的XAML,我将SelectedValue绑定到ComboBox.SelectedIndex ,而不是ComboBox.SelectedItem 。 这就是我必须在ConvertBack方法中使用Enum.ToObject的原因。 在修复XAML并通过调试器运行示例后,我意识到我只能从ConvertBack方法返回value ,因此值本身是Enum类型。

我知道这是一个老问题,但由于某种原因,这是相当复杂的,即使它似乎是一个非常常见的任务(我目前在UWP应用程序上这样做)。 结合已接受的答案,我发现的其他一些项目,以及我自己的一些工作,这是我发现完成这项琐事的最简单方法。 简而言之:

  • 定义您的枚举沿着/在Display属性中设置描述
  • 创建一个从枚举值转换为描述的转换器
  • 在viewmodel中,公开要从中选择的枚举值的集合,所选的枚举值,然后初始化它们
  • 定义一些方便的枚举扩展方法
  • 最后,一些简单的绑定到ComboBox,只是覆盖其ItemTemplate以使用转换器。

枚举

 public enum EnumOptions { [Display(Description = "Option 1")] OptionOne= 1, [Display(Description = "Option 2")] OptionTwo, [Display(Description = "Option 3")] OptionThree } 

变流器

 public class EnumToDisplayConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { var enumValue = value as Enum; return enumValue == null ? DependencyProperty.UnsetValue : enumValue.GetDescriptionFromEnumValue(); } public object ConvertBack(object value, Type targetType, object parameter, string language) { return value; } } 

Viewmodel(部分)

 public IReadOnlyList Options { get; } private EnumOptions _selectedOption; public EnumOptions SelectedOption { get { return _selectedOption; } set { _selectedOption = value; OnPropertyChanged(() => SelectedOption); } } // Initialization in constructor Options = EnumExtensions.GetValues().ToArray(); // If you want to set a default. SelectedOption = Options[0]; 

扩展

 public static class EnumExtensions { public static string GetDescriptionFromEnumValue(this Enum value) { var attribute = value.GetType() .GetField(value.ToString()) .GetCustomAttributes(typeof(DisplayAttribute), false) .SingleOrDefault() as DisplayAttribute; return attribute == null ? value.ToString() : attribute.Description; } ///  /// Enumerates all enum values ///  /// Enum type /// IEnumerable containing all enum values ///  public static IEnumerable GetValues() { return Enum.GetValues(typeof (T)).Cast(); } } 

XAML(部分)

 Choose an option        
 [ValueConversion(typeof(MyEnum), typeof(String))] public class MyEnumConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var enumVal = (MyEnum)value; // in this example, this is an extension method return enumValue.Description(); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { var enumDesc = value as string; MyEnum val; if (Enum.TryParse(typeof(MyEnum), strValue, out val)) { return val; } return DependencyProperty.UnsetValue; } } 

示例中的扩展方法可能如下所示:

 public static string Description(this MyEnum enumVal) { // you could use a switch statement here; // or maybe a Dictionary } 

以上示例的补充,以显示使用属性装饰枚举。

 sealed class DescriptionAttribute : Attribute { readonly string description; public DescriptionAttribute(string description) { this.description = description; } public string Description { get { return description; } } } enum Vehicle { [Description("Benz")] Car, [Description("Volvo")] Bus, [Description("Honda")] Bike } 

顺便说一句,我想知道为什么你需要将描述转换回enum。 如果您将枚举本身作为ItemSource提供,则可以使用描述技术在ComboBox中显示显示值,但是,一旦选择了某个项目,您就可以直接将枚举作为所选项目。

这是我工作良好的例子:

枚举定义:

 public enum MyEnum { [Description("Exchange 2007")] E2007, [Description("Exchange 2010")] E2010, [Description("Exchange 2013")] E2013, }; 

助手class:

 public static class cHelperClass { #region GetValuesAndDescriptions public static object[] GetValuesAndDescriptions(Type enumType) { var kvPairList = new List>(); var listValue = Enum.GetValues(enumType); for (var i = 0; i < listValue.Length; i++) { var value = listValue.GetValue(i); var enumValue = (Enum)listValue.GetValue(i); kvPairList.Add(new KeyValuePair(value.ToString(), GetDescription(enumValue))); } var valuesAndDescriptions = from kv in kvPairList select new { Value = kv.Key, Description = kv.Value }; return valuesAndDescriptions.ToArray(); } public static string GetDescription(this Enum value) { var fieldInfo = value.GetType().GetField(value.ToString()); var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); return (attributes.Length > 0) ? attributes[0].Description : value.ToString(); } public static string GetStringValue(this Enum enumItem) { return enumItem .GetType() .GetField(enumItem.ToString()) .GetCustomAttributes() .Select(a => a.Value) .FirstOrDefault() ?? enumItem.ToString(); } public static string GetName(Type enumType, object value) { return Enum.GetName(enumType, value); } #endregion } 

XAML: