Sé que llego tarde a la fiesta en esto, pero pensé que podría encontrar esta variante útil, ya que esta también le permite usar cadenas descriptivas en lugar de constantes de enumeración en el menú desplegable. Para hacer esto, decore cada entrada de enumeración con un atributo [System.ComponentModel.Description].
Por ejemplo:
public enum TestEnum
{
[Description("Full test")]
FullTest,
[Description("Incomplete or partial test")]
PartialTest,
[Description("No test performed")]
None
}
Aquí está mi código:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Reflection;
using System.ComponentModel;
using System.Linq.Expressions;
...
private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
{
Type realModelType = modelMetadata.ModelType;
Type underlyingType = Nullable.GetUnderlyingType(realModelType);
if (underlyingType != null)
{
realModelType = underlyingType;
}
return realModelType;
}
private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };
public static string GetEnumDescription<TEnum>(TEnum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if ((attributes != null) && (attributes.Length > 0))
return attributes[0].Description;
else
return value.ToString();
}
public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
{
return EnumDropDownListFor(htmlHelper, expression, null);
}
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 = GetEnumDescription(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);
}
Luego puede hacer esto desde su punto de vista:
@Html.EnumDropDownListFor(model => model.MyEnumProperty)
¡Espero que esto te ayude!
** EDITAR 2014-ENE-23: Microsoft acaba de lanzar MVC 5.1, que ahora tiene una función EnumDropDownListFor. Lamentablemente, no parece respetar el atributo [Descripción], por lo que el código anterior sigue en pie. Consulte la sección Enum en las notas de la versión de Microsoft para MVC 5.1.
Actualización: sin embargo, admite el atributo Display[Display(Name = "Sample")]
, por lo que uno puede usarlo.
[Actualización: acabo de notar esto y el código parece una versión extendida del código aquí: https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a- dropdownlist-helper-for-enums / , con un par de adiciones. Si es así, la atribución parecería justa ;-)]