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

后端 未结 30 1910
不知归路
不知归路 2020-11-21 16:36

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

相关标签:
30条回答
  • 2020-11-21 16:57

    I bumped into the same problem, found this question, and thought that the solution provided by Ash wasn't what I was looking for; Having to create the HTML myself means less flexibility compared to the built-in Html.DropDownList() function.

    Turns out C#3 etc. makes this pretty easy. I have an enum called TaskStatus:

    var statuses = from TaskStatus s in Enum.GetValues(typeof(TaskStatus))
                   select new { ID = s, Name = s.ToString() };
    ViewData["taskStatus"] = new SelectList(statuses, "ID", "Name", task.Status);
    

    This creates a good ol' SelectList that can be used like you're used to in the view:

    <td><b>Status:</b></td><td><%=Html.DropDownList("taskStatus")%></td></tr>
    

    The anonymous type and LINQ makes this so much more elegant IMHO. No offence intended, Ash. :)

    0 讨论(0)
  • 2020-11-21 16:58

    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 Enum section in Microsoft's release notes for MVC 5.1.

    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: https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums/, with a couple of additions. If so, attribution would seem fair ;-)]

    0 讨论(0)
  • 2020-11-21 16:58

    You want to look at using something like Enum.GetValues

    0 讨论(0)
  • 2020-11-21 17:00

    In .NET Core you can just use this:

    @Html.DropDownListFor(x => x.Foo, Html.GetEnumSelectList<MyEnum>())
    
    0 讨论(0)
  • 2020-11-21 17:02
    @Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
    
    0 讨论(0)
  • 2020-11-21 17:02

    I found an answer here. However, some of my enums have [Description(...)] attribute, so I've modified the code to provide support for that:

        enum Abc
        {
            [Description("Cba")]
            Abc,
    
            Def
        }
    
    
        public static MvcHtmlString EnumDropDownList<TEnum>(this HtmlHelper htmlHelper, string name, TEnum selectedValue)
        {
            IEnumerable<TEnum> values = Enum.GetValues(typeof(TEnum))
                .Cast<TEnum>();
    
            List<SelectListItem> items = new List<SelectListItem>();
            foreach (var value in values)
            {
                string text = value.ToString();
    
                var member = typeof(TEnum).GetMember(value.ToString());
                if (member.Count() > 0)
                {
                    var customAttributes = member[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                    if (customAttributes.Count() > 0)
                    {
                        text = ((DescriptionAttribute)customAttributes[0]).Description;
                    }
                }
    
                items.Add(new SelectListItem
                {
                    Text = text,
                    Value = value.ToString(),
                    Selected = (value.Equals(selectedValue))
                });
            }
    
            return htmlHelper.DropDownList(
                name,
                items
                );
        }
    

    Hope that helps.

    0 讨论(0)
提交回复
热议问题