13

如何将enumwith Description( DescriptionAttribute) 绑定到 a ComboBox

我有一个enum

public enum ReportTemplate
{
    [Description("Top view")]
    TopView,

    [Description("Section view")]
    SectionView
}

我试过这个:

<ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type System:Enum}"
                    x:Key="ReportTemplateEnum">
    <ObjectDataProvider.MethodParameters>
        <x:Type TypeName="Helpers:ReportTemplate"/>
    </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

<Style x:Key="ReportTemplateCombobox" TargetType="dxe:ComboBoxEditSettings">
    <Setter Property="ItemsSource" 
            Value="{Binding Source={x:Type Helpers:ReportTemplate}}"/>
    <Setter Property="DisplayMember" Value="Description"/>
    <Setter Property="ValueMember" Value="Value"/>
</Style>

不能成功做到这一点,任何简单的解决方案?

提前致谢!

4

4 回答 4

22

这可以通过为您的组合框使用转换器和项目模板来完成。

这是绑定到枚举时将返回描述值的转换器代码:

namespace FirmwareUpdate.UI.WPF.Common.Converters
{
    public class EnumDescriptionConverter : IValueConverter
    {
        private string GetEnumDescription(Enum enumObj)
        {
            FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString());

            object[] attribArray = fieldInfo.GetCustomAttributes(false);

            if (attribArray.Length == 0)
            {
                return enumObj.ToString();
            }
            else
            {
                DescriptionAttribute attrib = attribArray[0] as DescriptionAttribute;
                return attrib.Description;
            }
        }

        object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Enum myEnum = (Enum)value;
            string description = GetEnumDescription(myEnum);
            return description;
        }

        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return string.Empty;
        }
    }
}

然后在您的 xaml 中您需要使用和项目模板。

<ComboBox Grid.Row="1" Grid.Column="1"  Height="25" Width="100" Margin="5"
              ItemsSource="{Binding Path=MyEnums}"
              SelectedItem="{Binding Path=MySelectedItem}"
              >
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Converter={StaticResource enumDescriptionConverter}}"/>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
于 2013-11-15T18:06:44.633 回答
5

RSmaller 有一个很好的答案,也是我使用的那个,但有一点需要注意。如果您的枚举中有多个属性,并且 Description 不是第一个列出的,那么他的“GetEnumDescription”方法将引发异常......

这是一个稍微安全一点的版本:

    private string GetEnumDescription(Enum enumObj)
    {
        FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString());

        object[] attribArray = fieldInfo.GetCustomAttributes(false);

        if (attribArray.Length == 0)
        {
            return enumObj.ToString();
        }
        else
        {
            DescriptionAttribute attrib = null;

            foreach( var att in attribArray)
            {
                if (att is DescriptionAttribute)
                    attrib = att as DescriptionAttribute;
            }

            if (attrib != null )
                return attrib.Description;

            return enumObj.ToString();
        }
    }
于 2017-11-01T21:46:40.290 回答
0

虽然已经回答,但我通常使用类型转换器执行以下操作。

  1. 我向我的枚举添加了一个类型转换器属性。

    // MainWindow.cs, or any other class
    [TypeConverter(TypeOf(MyDescriptionConverter)]
    public enum ReportTemplate
    { 
         [Description("Top view")]
         TopView,
    
         [Description("Section view")]
         SectionView
    }
    
  2. 实现类型转换器

    // Converters.cs
    public class MyDescriptionConverter: EnumConverter
    {
        public MyDescriptionConverter(Type type) : base(type) { }
    
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
             if (destinationType == typeof(string))
             {
                 if (value != null)
                 {
                     FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
    
                 if (fieldInfo != null)
                 {
                     var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
    
                     return ((attributes.Length > 0) && (!string.IsNullOrEmpty(attributes[0].Description))) ? attributes[0].Description : value.ToString();
                 }
             }
    
             return string.Empty;
         }
    
         return base.ConvertTo(context, culture, value, destinationType);
     }
    
  3. 提供要绑定的属性

    // myclass.cs, your class using the enum
    public class MyClass()
    {
        // Make sure to implement INotifyPropertyChanged, but you know how to do it
        public MyReportTemplate MyReportTemplate { get; set; }
    
        // Provides the bindable enumeration of descriptions
        public IEnumerable<ReportTemplate> ReportTemplateValues
        {
             get { return Enum.GetValues(typeof(ReportTemplate)).Cast<ReportTemplate>(); }
        }
    }
    
  4. 使用枚举属性绑定组合框。

     <!-- MainWindow.xaml -->
     <ComboBox ItemsSource="{Binding ReportTemplateValues}"
               SelectedItem="{Binding MyReportTemplate}"/>
    
     <!-- Or if you just want to show the selected vale -->
     <TextBlock Text="MyReportTemplate"/>
    

我喜欢这种方式,我的 xaml 保持可读性。如果缺少枚举项属性之一,则使用项本身的名称。

于 2021-07-26T13:13:18.053 回答
-5
public enum ReportTemplate
{
 [Description("Top view")]
 Top_view=1,
 [Description("Section view")]
 Section_view=2
}

ComboBoxEditSettings.ItemsSource = EnumHelper.GetAllValuesAndDescriptions(new
List<ReportTemplate> { ReportTemplate.Top_view, ReportTemplate.Section_view });
于 2014-07-06T08:18:12.290 回答