Reputation: 703
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
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:
Ressoures:
Upvotes: 2
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
Reputation: 222582
You should use Enum Extenstion class or Value Converter to do this,
wpf-databinding-enum-with-nice-descriptions
Upvotes: 0