Reputation: 95
I have a enum that holds countries:
public enum CountryEnum
{
[Display(Name = "AF", ResourceType = typeof(Global))]
AF,
[Display(Name = "AL", ResourceType = typeof(Global))]
AL,
[Display(Name = "DZ", ResourceType = typeof(Global))]
DZ,
};
As you can see I make use of the DataAnnotations to localise the values.
Now I want to display a dropdownlist with all of the localised country names. I come up with this code:
public static string GetDisplayName<TEnum>(TEnum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DisplayAttribute[] attributes =
(DisplayAttribute[])fi.GetCustomAttributes(
typeof(DisplayAttribute), false);
if ((attributes != null) && (attributes.Length > 0))
return attributes[0].Name;
else
return value.ToString();
}
I have a Html helper that makes use of the above method:
public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Type enumType = GetNonNullableModelType(metadata);
IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();
IEnumerable<SelectListItem> items = from value in values
select new SelectListItem
{
Text = GetDisplayName(value),
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
};
// If the enum is nullable, add an 'empty' item to the collection
if (metadata.IsNullableValueType)
items = SingleEmptyItem.Concat(items);
return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
}
The DropDown renders correctly, however, GetDisplayName
doesn't return the localised value, it just display the name attribute (e.g. AF for the first entry).
How can I modify GetDisplayName
method to return the localised value?
Upvotes: 0
Views: 2159
Reputation: 162
I was having a similar problem, having setup the Display Attribute as you did (easier since classes use the same attribute to load localizations), so took your initial code and tweaked it a bit, now it is displaying the localization string as expected. I don't think it is the most clever or optimized way of doing it, but it works. Hopefully that's what you intended.
public static string GetDisplayName<TEnum>(TEnum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DisplayAttribute[] attributes = (DisplayAttribute[])fi.
GetCustomAttributes(typeof(DisplayAttribute), false);
if ((attributes != null) && (attributes.Length > 0))
{
string key = attributes[0].Name;
string localizedString = attributes[0].ResourceType.GetProperty(key).GetValue("").ToString();
return localizedString;
}
else
return value.ToString();
}
Upvotes: 0
Reputation: 13177
You need to update your GetDisplayName
method to use the GetName()
method rather than the Name
property of the DisplayAttribute
.
Like this:
public static string GetDisplayName<TEnum>(TEnum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DisplayAttribute[] attributes = (DisplayAttribute[])fi.
GetCustomAttributes(typeof(DisplayAttribute), false);
if ((attributes != null) && (attributes.Length > 0))
return attributes[0].GetName();
else
return value.ToString();
}
From the MSDN documentation for DisplayAttribute.Name
:
Do not use this property to get the value of the Name property. Use the GetName method instead.
The MSDN documentation for the GetName()
method has this to say:
Returns the localized string for the Name property, if the ResourceType property has been specified and the Name property represents a resource key; otherwise, the non-localized value of the Name property.
Upvotes: 2