2

We know that if we define a template for a base type, that template could serve also for the derived types (if any other template was not used to override it).

As we can't inherit an Enum, nor enums are considered inherited from the Enum, so neither the Enum.cshtml template in the Views\Shared\EditorTemplates will not be active for different custom enum properties of the objects, like this one:

public enum Role
{
    Admin,
    User,
    Guest
}

I already saw some answers on this topic for ASP in general, but I am wondering if in MVC 4 there are some improvements on this subject?

PS. I mean without use any explicit template attribution (like @Html.EditorFor(model => model.Role, "Enum") or [UIHint("Enum")])

PPS. I am novice in MVC, so I'll appreciate your simple answers.

serge
  • 13,940
  • 35
  • 121
  • 205

3 Answers3

7

K. Scott Allen has a nice article about this.

Stacked
  • 6,892
  • 7
  • 57
  • 73
lajjne
  • 699
  • 5
  • 15
1

In MVC 5, you can add a template to Views->Shared->EditorTemplates containing this code:

@model Enum
@{
    var optionLabel = ViewData["optionLabel"] as string;
    var htmlAttributes = ViewData["htmlAttributes"];
}
@Html.EnumDropDownListFor(m => m, optionLabel, htmlAttributes)

Example usage:

@Html.EditorFor(model => model.PropertyType, 
                new { 
                       htmlAttributes = new { @class = "form-control" },
                       optionLabel = "Select" 
                    })

In MVC 4, you don't have the EnumDropDownListFor extension, but you could roll your own, which I did previously like this:

public static MvcHtmlString DropDownListFor<TModel, TEnum>
   (this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TEnum>> expression, 
    string optionLabel = null, object htmlAttributes = null)
{
    //This code is based on the blog - it's finding out if it nullable or not
    Type metaDataModelType = ModelMetadata
       .FromLambdaExpression(expression, htmlHelper.ViewData).ModelType;
    Type enumType = Nullable.GetUnderlyingType(metaDataModelType) ?? metaDataModelType;

    if (!enumType.IsEnum)
        throw new ArgumentException("TEnum must be an enumerated type");  


    IEnumerable<SelectListItem> items = Enum.GetValues(enumType).Cast<TEnum>()
       .Select(e => new SelectListItem
               {
                  Text = e.GetDisplayName(),
                  Value = e.ToString(),
                  Selected = e.Equals(ModelMetadata
                     .FromLambdaExpression(expression, htmlHelper.ViewData).Model)
               });

    return htmlHelper.DropDownListFor(
        expression,
        items,
        optionLabel,
        htmlAttributes
        );
}

References:

http://stackoverflow.com/questions/79126/create-generic-method-constraining-t-to-an-enum

http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums.aspx

Colin
  • 22,328
  • 17
  • 103
  • 197
0

Also; there is:

@Html.EnumDropDownListFor(model => model.Role, new { @class = ".." })

Role being the enum of course :)

Christian
  • 394
  • 2
  • 17