Reputation: 121649
I have an enumeration that looks like this:
BoT_DropdownValues.cs:
public class BoT_DropdownValues
{
public enum BlockSizes
{
[Display(Name = "12 Months")]
M12,
[Display(Name = "24 Months")]
M24,
[Display(Name = "36 Months")]
M36,
[Display(Name = "48 Months")]
M48,
[Display(Name = "60 Months")]
M60
}
I want to choose one of the items from "select" element:
CreateBoT.cshtml:
<div class="form-group" id="Q3_div">
@Html.DropDownListFor(m =>
m.BoT_Answers.Q3,
new SelectList(Enum.GetValues(typeof(BoT_DropdownValues.BlockSizes))),
"Select One",
new { @class = "custom-select", @id = "BoT_Answers_Q3" })
...
Problem:
This syntax gives me "M12","M24", "M36", ... in the dropdown. I'd LIKE the dropdown to show the [Display()] names: "12 Months", "24 Months", etc. to the user.
Q: Is there syntax I can use with @Html.DropDownListFor()
to achieve this?
Update
Most of the answers I found involved writing a static extensions class and much extra work. I'm still looking for a "better answer", but for now this seems to give me everything I'm looking for:
@Html.DropDownListFor(m =>
m.BoT_Answers.Q3,
new List<SelectListItem>
{
new SelectListItem {Text="Select One", Value="", Selected=true },
new SelectListItem {Text="12 Months", Value="12" },
new SelectListItem {Text="24 Months", Value="24" },
new SelectListItem {Text="36 Months", Value="36" },
new SelectListItem {Text="48 Months", Value="48" },
new SelectListItem {Text="60 Months", Value="60" }
},
new { @class = "custom-select", @id = "BoT_Answers_Q3" })
Q: Can anybody think of any disadvantages to this approach?
Upvotes: 1
Views: 564
Reputation: 11100
You're going to need to write a method, or use someone else's. Here's mine;
public static class EnumHelper<T> where T:struct, Enum{
public static List<(T value, string display)> Values =
typeof(T)
.GetFields(BindingFlags.Static | BindingFlags.Public)
.OrderBy(f => f.MetadataToken)
.Select(f => (
(T)f.GetValue(null),
f.GetCustomAttribute<DisplayNameAttribute>()?.DisplayName
?? f.GetCustomAttribute<DisplayAttribute>()?.Name
?? f.Name
))
.ToList();
}
public static class Extensions{
public static IEnumerable<SelectListItem> SelectList<T>(this IHtmlHelper html) where T:struct, Enum
=> EnumHelper<T>.Values.Select(v => new SelectListItem(v.display, v.value.ToString()));
}
<select asp-items="Html.SelectList<BlockSizes>()"></select>
Upvotes: 1
Reputation: 2444
I tested following using helper class and it worked. So valuesToDisplay = ["12 months", "24 months" etc...]:
var valuesToDisplay = GetDisplayValues();
static List<string> GetDisplayValues() {
List<string> ret = new List<string>();
var enumValues = Enum.GetValues(typeof(BlockSizes));
foreach (var value in enumValues)
{
ret.Add(EnumHelper<BlockSizes>.GetDisplayValue((BlockSizes)value));
}
return ret;
}
public static class EnumHelper<T>
{
public static IList<T> GetValues(Enum value)
{
var enumValues = new List<T>();
foreach (FieldInfo fi in value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public))
{
enumValues.Add((T)Enum.Parse(value.GetType(), fi.Name, false));
}
return enumValues;
}
public static T Parse(string value)
{
return (T)Enum.Parse(typeof(T), value, true);
}
public static IList<string> GetNames(Enum value)
{
return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList();
}
public static IList<string> GetDisplayValues(Enum value)
{
return GetNames(value).Select(obj => GetDisplayValue(Parse(obj))).ToList();
}
private static string lookupResource(Type resourceManagerProvider, string resourceKey)
{
foreach (PropertyInfo staticProperty in resourceManagerProvider.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
{
if (staticProperty.PropertyType == typeof(System.Resources.ResourceManager))
{
System.Resources.ResourceManager resourceManager = (System.Resources.ResourceManager)staticProperty.GetValue(null, null);
return resourceManager.GetString(resourceKey);
}
}
return resourceKey; // Fallback with the key name
}
public static string GetDisplayValue(T value)
{
var fieldInfo = value.GetType().GetField(value.ToString());
var descriptionAttributes = fieldInfo.GetCustomAttributes(
typeof(DisplayAttribute), false) as DisplayAttribute[];
if (descriptionAttributes[0].ResourceType != null)
return lookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Name);
if (descriptionAttributes == null) return string.Empty;
return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString();
}
}
Upvotes: 1