简体   繁体   中英

WPF How to bind an enum with Description to a ComboBox

How can I bind an enum with Description ( DescriptionAttribute ) to a ComboBox ?

I got an enum :

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

    [Description("Section view")]
    SectionView
}

I tried this:

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

Can't succeed to do this, any simple solution?

Thanks in advance!

This can be done by using a converter and item template for your comboBox.

Here is the converter code which when bound to an enum will return the Description value:

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

Then in your xaml you need to use and item template.

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

RSmaller has a good answer, and is the one I use as well, with one caveat. If you have more than one attribute on your enums, and Description isn't the first listed then his "GetEnumDescription" method will throw an exception...

Here is a slightly safer version:

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

Although already answered, I usually do the following, using a type converter.

  1. I add a type converter attribute to my enums.

     // MainWindow.cs, or any other class [TypeConverter(TypeOf(MyDescriptionConverter)] public enum ReportTemplate { [Description("Top view")] TopView, [Description("Section view")] SectionView }
  2. Implement the type converter

    // 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. Provide a property to bind

    // 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. Bind the combobox using the enumeration property.

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

I like this way, my xaml stays readable. If one of the enumeration item attributes is missing, the name of the item itself is used.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM