user2877989
user2877989

Reputation: 703

How to display enum's [Description] in DataGrid

I'm building an WPF application.

My DataGrid display rows with data from

ItemSrouce="{Bingding Accounts}"

in C#

accountListViewModel.Accounts = entityService.Accounts; // each record is an instance of Account class

The Account class have an Enum propery named Genders. The Enum like this:

public enum MyEnum
{
    [Description("MyEnum1 Description")]
    MyEnum1,
    [Description("MyEnum2 Description")]
    MyEnum2,
    [Description("MyEnum3 Description")]
    MyEnum3
}

How to make my DataGrid in WPF display the description instead of enum name ?

Upvotes: 1

Views: 3156

Answers (3)

Robetto
Robetto

Reputation: 789

What you're really asking for is a TypeConverter

For the DataGrid it is seemingly not enough to just have EnumMember or Description on your enumeration members decorated. It also wants to have the actual type to be decorated with a [TypeConverter(typeof(YourConverter))]. There exists an EnumConverter in ComponentModel, however it is not attribute aware - just 'ToString()'s the enum members.

Therefore my suggestion is:

This may be your enum:

[TypeConverter(typeof(EnumDescriptionTypeConverter))]
public enum ComparisonOperators
{
    [Description("=")]
    [EnumMember(Value = "=")]
    Equal,

    [Description("<>")]
    [EnumMember(Value = "<>")]
    Unequal,

    [Description("<")]
    [EnumMember(Value = "<")]
    LessThan,

    [Description("<=")]
    [EnumMember(Value = "<=")]
    LessThanOrEqual,

    [Description(">")]
    [EnumMember(Value = ">")]
    GreaterThan,

    [Description(">=")]
    [EnumMember(Value = ">=")]
    GreaterThanOrEqual
}

Then you need the mentioned EnumDescriptionTypeConverter (Note that it respects EnumMember and Description attributes in the same way):

    public class EnumDescriptionTypeConverter : EnumConverter
{
    public EnumDescriptionTypeConverter(Type type)
        : base(type)
    {
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(string))
        {
            if (value != null)
            {
                FieldInfo fi = value.GetType().GetField(value.ToString());
                if (fi != null)
                {
                    var dattributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
                    var eattributes = (EnumMemberAttribute[])fi.GetCustomAttributes(typeof(EnumMemberAttribute), false);
                    return dattributes.Select(d => d.Description).Concat(eattributes.Select(e => e.Value))
                               .FirstOrDefault() ?? string.Empty;
                }
            }

            return string.Empty;
        }

        return base.ConvertTo(context, culture, value, destinationType);
    }
}

Then you just bind your ViewModel to the DataGrid:

<DataGrid ItemsSource="{Binding Vm}" />

Auto generate being enabled, it will display all Enum members as comboboxes.

Example VM:

public class MyVm : ViewModelBase
{
    [DisplayName("Number")]
    [Description("Provide a number")]
    public int OrdinaaryOrdinal {get; set;}

    [DisplayName("Compare operator")]
    [Description("to do")]
    public ComparisonOperators Operator {get; set;}
    ...

et viola it is displayed as supposed:

Grid running with that enum type.

Ressoures:

Upvotes: 2

martavoi
martavoi

Reputation: 7092

You can create custom value converter for your cell binding and put in it logic for retrieving attribute value.

public class EnumDescriptionConverter : IValueConverter
{
    private string GetEnumDescription(Enum enumObj)
    {
        FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString());
        var descriptionAttr = fieldInfo
                                      .GetCustomAttributes(false)
                                      .OfType<DescriptionAttribute>()
                                      .Cast<DescriptionAttribute>()
                                      .SingleOrDefault();
        if (descriptionAttr == null)
        {
            return enumObj.ToString();
        }
        else
        {
            return descriptionAttr.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;
    }
}

Upvotes: 4

Sajeetharan
Sajeetharan

Reputation: 222582

You should use Enum Extenstion class or Value Converter to do this,

wpf-databinding-enum-with-nice-descriptions

Upvotes: 0

Related Questions