将ComboBox的SelectedValue绑定到WPF中的枚举

我想在ListView中显示产品列表,其中一列是我想要绑定的ComboBox 。 这是我的枚举:

 public enum SelectionMode { One, Two } 

和产品类:

 public class Product { public SelectionMode Mode { get; set; } public string Name { get; set; } } 

ViewModel类中,我有一个ProductObservableCollection

  private ObservableCollection _productList; public ObservableCollection ProductList { get { return _productList; } set { _productList = value; } } public MainViewModel() { ProductList = new ObservableCollection { new Product {Mode = SelectionMode.One, Name = "One"}, new Product {Mode = SelectionMode.One, Name = "One"}, new Product {Mode = SelectionMode.Two, Name = "Two"} }; } 

最后我有一个带有ListViewGrid ,它绑定到我的ProductList

                        

我的问题是; 将ComboBox SelectedValue绑定到Product类的SelectionMode属性的方法是什么?

更新

好。 我在这个主题中找到了答案。 所以我必须添加转换器类:

 public class MyEnumToStringConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value.ToString(); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return (SelectionMode)Enum.Parse(typeof(SelectionMode), value.ToString(), true); } } 

并将其添加到窗口资源:

         

最后编辑ComboBox数据模板:

  

就这样。 希望它对别人有用:)

如果您准备更改ComboBox的ItemsSource的绑定,那么,只需SelectedValue="{Binding Mode,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"将起作用。

在这种情况下,您必须像这样绑定ItemsSource: ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ViewClass}}, Path=ModeList}" ; 其中,ModeList是SelectionMode类型列表的简单公共属性,包含应该在ComboBox下拉列表中显示的枚举,而ViewClass是此属性(ModeList)可用的类; 确保在xaml中添加了名称空间的引用。

否则你必须使用转换器,它应该将字符串转换回枚举类型。

下面我将绑定枚举用于列表/ combox

 public enum EnumsAvailable { [Description("Its an A")] a, [Description("Its a B")] b, [Description("Its a C")] c, [Description("Its a D")] d } ; 

这是我的XAML

   

我的视图模型

  public EnumsAvailable ListOfEnumValues { get { return new EnumsAvailable(); } } public EnumsAvailable ChosenEnum { get { return _ChosenEnum; } set { if (_ChosenEnum != value) { _ChosenEnum = value; RaisePropertyChanged(() => ChosenEnum); } } } 

和我的转换器

 public class ArrayStringToEnumDescriptionConverter : BaseEnumDescriptionConverter, IValueConverter { public ArrayStringToEnumDescriptionConverter() { } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var type = value.GetType(); return !type.IsEnum ? null : base.GetEnumDescription(type); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; } } public abstract class BaseEnumDescriptionConverter : MarkupExtension { public override object ProvideValue(IServiceProvider serviceProvider) { return this; } public IEnumerable GetEnumDescription(Type destinationType) { var enumType = destinationType; var values = RetrieveEnumDescriptionValues(enumType); return new List(values); } public object GetEnumFromDescription(string descToDecipher, Type destinationType) { var type = destinationType; if (!type.IsEnum) throw new InvalidOperationException(); var staticFields = type.GetFields().Where(fld => fld.IsStatic); foreach (var field in staticFields) { var attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; if (attribute != null) { if (attribute.Description == descToDecipher) { return (Enum.Parse(type, field.Name, true)); } } else { if (field.Name == descToDecipher) return field.GetValue(null); } } throw new ArgumentException("Description is not found in enum list."); } public static string[] RetrieveEnumDescriptionValues(Type typeOfEnum) { var values = Enum.GetValues(typeOfEnum); return (from object fieldInfo in values select DescriptionAttr(fieldInfo)).ToArray(); } public static string DescriptionAttr(object enumToQuery) { FieldInfo fi = enumToQuery.GetType().GetField(enumToQuery.ToString()); DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes( typeof(DescriptionAttribute), false); return attributes.Length > 0 ? attributes[0].Description : enumToQuery.ToString(); } public static string GetDomainNameAttribute(object enumToQuery) { FieldInfo fi = enumToQuery.GetType().GetField(enumToQuery.ToString()); DomainNameAttribute[] attributes = (DomainNameAttribute[])fi.GetCustomAttributes( typeof(DomainNameAttribute), false); return attributes.Length > 0 ? attributes[0].DomainName : enumToQuery.ToString(); } } public class DescriptionToEnumConverter : BaseEnumDescriptionConverter, IValueConverter { public DescriptionToEnumConverter(){} public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var enumValue = value; if (enumValue != null) { enumValue = GetEnumFromDescription(value.ToString(), targetType); } return enumValue; } } 

在我个人看来,它有很多清洁和高度可重复使用。 到目前为止,我发现的唯一缺陷是,如果您更新代码中的选定值(不是通过UI),那么它不会在UI上更新。 但是,这可以通过进一步的UI调整来克服。 我现在正在进行更改,一旦完成,我将更新此答案。

我正在使用转换器,它还允许定义将显示的字符串而不是枚举值: http : //www.ageektrapped.com/blog/the-missing-net-7-displaying-enums-在-WPF /