How do you create a dropdownlist from an enum in ASP.NET MVC?

I'm trying to use the Html.DropDownList extension method but can't figure out how to use it with an enumeration.

Let's say I have an enumeration like this:

public enum ItemTypes
{
    Movie = 1,
    Game = 2,
    Book = 3
}

How do I go about creating a dropdown with these values using the Html.DropDownList extension method?

Or is my best bet to simply create a for loop and create the Html elements manually?


For MVC v5.1 use Html.EnumDropDownListFor

@Html.EnumDropDownListFor(
    x => x.YourEnumField,
    "Select My Type", 
    new { @class = "form-control" })

For MVC v5 use EnumHelper

@Html.DropDownList("MyType", 
   EnumHelper.GetSelectList(typeof(MyType)) , 
   "Select My Type", 
   new { @class = "form-control" })

For MVC 5 and lower

I rolled Rune's answer into an extension method:

namespace MyApp.Common
{
    public static class MyExtensions{
        public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
            where TEnum : struct, IComparable, IFormattable, IConvertible
        {
            var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                select new { Id = e, Name = e.ToString() };
            return new SelectList(values, "Id", "Name", enumObj);
        }
    }
}

This allows you to write:

ViewData["taskStatus"] = task.Status.ToSelectList();

by using MyApp.Common


I know I'm late to the party on this, but thought you might find this variant useful, as this one also allows you to use descriptive strings rather than enumeration constants in the drop down. To do this, decorate each enumeration entry with a [System.ComponentModel.Description] attribute.

For example:

public enum TestEnum
{
  [Description("Full test")]
  FullTest,

  [Description("Incomplete or partial test")]
  PartialTest,

  [Description("No test performed")]
  None
}

Here is my code:

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);
    }

You can then do this in your view:

@Html.EnumDropDownListFor(model => model.MyEnumProperty)

Hope this helps you!

EDIT 2014-JAN-23: Microsoft have just released MVC 5.1, which now has an EnumDropDownListFor feature. Sadly it does not appear to respect the [Description] attribute so the code above still stands. (See http://www.asp.net/mvc/overview/releases/mvc51-release-notes#Enum for Microsoft's release notes.)

Update: It does support the Display attribute [Display(Name = "Sample")] though, so one can use that.

[Update - just noticed this, and the code looks like an extended version of the code here: http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums.aspx, with a couple of additions. If so, attribution would seem fair ;-)]


In ASP.NET MVC 5.1 , they added the EnumDropDownListFor() helper, so no need for custom extensions:

Model:

public enum MyEnum
{
    [Display(Name = "First Value - desc..")]
    FirstValue,
    [Display(Name = "Second Value - desc...")]
    SecondValue
}

View:

@Html.EnumDropDownListFor(model => model.MyEnum)

Using Tag Helper (ASP.NET MVC 6):

<select asp-for="@Model.SelectedValue" asp-items="Html.GetEnumSelectList<MyEnum>()">
链接地址: http://www.djcxy.com/p/8426.html

上一篇: 你如何处理ASP.NET MVC框架中的多个提交按钮?

下一篇: 你如何从ASP.NET MVC中的枚举创建一个下拉列表?