如何从ASP.NET MVC中的枚举创建下拉列表?

时间:2008-12-23 09:25:43

标签: c# asp.net asp.net-mvc

我正在尝试使用Html.DropDownList扩展方法,但无法弄清楚如何将它与枚举一起使用。

假设我有一个这样的枚举:

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

如何使用Html.DropDownList扩展方法创建包含这些值的下拉列表?

或者我最好还是简单地创建一个for循环并手动创建Html元素?

36 个答案:

答案 0 :(得分:792)

对于MVC v5.1,使用Html.EnumDropDownListFor

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

对于MVC v5,请使用EnumHelper

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

对于MVC 5及更低版本

我将Rune的答案转换为扩展方法:

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

这允许你写:

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

using MyApp.Common

答案 1 :(得分:349)

我知道我迟到了,但是你认为这个变种很有用,因为这个变体也允许你在下拉列表中使用描述性字符串而不是枚举常量。为此,请使用[System.ComponentModel.Description]属性修饰每个枚举条目。

例如:

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

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

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

这是我的代码:

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

然后,您可以在视图中执行此操作:

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

希望这能帮到你!

**编辑2014-JAN-23:微软刚刚发布了MVC 5.1,它现在有一个EnumDropDownListFor功能。遗憾的是它似乎不尊重[Description]属性,因此上面的代码仍然有效。参见Enum section in Microsoft的MVC 5.1发行说明。

更新:它确实支持Display属性[Display(Name = "Sample")],因此可以使用该属性。

[更新 - 只是注意到了这一点,代码看起来像这里的代码的扩展版本:https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums/,有几个补充。如果是这样,归属似乎是公平的; - )]

答案 2 :(得分:185)

ASP.NET MVC 5.1 中,他们添加了EnumDropDownListFor()帮助器,因此无需自定义扩展程序:

模型

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

查看

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

使用Tag Helper(ASP.NET MVC 6)

<select asp-for="@Model.SelectedValue" asp-items="Html.GetEnumSelectList<MyEnum>()">

答案 3 :(得分:126)

我碰到了同样的问题,发现了这个问题,并认为Ash提供的解决方案不是我想要的;与内置的Html.DropDownList()函数相比,必须自己创建HTML意味着更少的灵活性。

原来C#3等让这很容易。我有enum名为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);

这会创建一个很好的“SelectList,可以像您在视图中习惯的那样使用:

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

匿名类型和LINQ使这个更优雅恕我直言。 Ash,没有违法行为。 :)

答案 4 :(得分:59)

这是一个更好的封装解决方案:

https://www.spicelogic.com/Blog/enum-dropdownlistfor-asp-net-mvc-5

说这是你的模特:

enter image description here

样本使用:

enter image description here

生成的用户界面 enter image description here

并生成HTML

enter image description here

帮助程序扩展源代码快照:

enter image description here

您可以从我提供的链接下载示例项目。

编辑:这是代码:

public static class EnumEditorHtmlHelper
{
    /// <summary>
    /// Creates the DropDown List (HTML Select Element) from LINQ 
    /// Expression where the expression returns an Enum type.
    /// </summary>
    /// <typeparam name="TModel">The type of the model.</typeparam>
    /// <typeparam name="TProperty">The type of the property.</typeparam>
    /// <param name="htmlHelper">The HTML helper.</param>
    /// <param name="expression">The expression.</param>
    /// <returns></returns>
    public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression) 
        where TModel : class
    {
        TProperty value = htmlHelper.ViewData.Model == null 
            ? default(TProperty) 
            : expression.Compile()(htmlHelper.ViewData.Model);
        string selected = value == null ? String.Empty : value.ToString();
        return htmlHelper.DropDownListFor(expression, createSelectList(expression.ReturnType, selected));
    }

    /// <summary>
    /// Creates the select list.
    /// </summary>
    /// <param name="enumType">Type of the enum.</param>
    /// <param name="selectedItem">The selected item.</param>
    /// <returns></returns>
    private static IEnumerable<SelectListItem> createSelectList(Type enumType, string selectedItem)
    {
        return (from object item in Enum.GetValues(enumType)
                let fi = enumType.GetField(item.ToString())
                let attribute = fi.GetCustomAttributes(typeof (DescriptionAttribute), true).FirstOrDefault()
                let title = attribute == null ? item.ToString() : ((DescriptionAttribute) attribute).Description
                select new SelectListItem
                  {
                      Value = item.ToString(), 
                      Text = title, 
                      Selected = selectedItem == item.ToString()
                  }).ToList();
    }
}

答案 5 :(得分:47)

Html.DropDownListFor只需要一个IEnumerable,因此Prize解决方案的替代方案如下。这将允许您简单地写:

@Html.DropDownListFor(m => m.SelectedItemType, Model.SelectedItemType.ToSelectList())

[其中SelectedItemType是类型为ItemTypes的模型上的字段,并且您的模型为非null]

此外,您不需要对扩展方法进行泛化,因为您可以使用enumValue.GetType()而不是typeof(T)。

编辑:此处集成了Simon的解决方案,并包含ToDescription扩展方法。

public static class EnumExtensions
{
    public static IEnumerable<SelectListItem> ToSelectList(this Enum enumValue)
    {
        return from Enum e in Enum.GetValues(enumValue.GetType())
               select new SelectListItem
               {
                   Selected = e.Equals(enumValue),
                   Text = e.ToDescription(),
                   Value = e.ToString()
               };
    }

    public static string ToDescription(this Enum value)
    {
        var attributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length > 0 ? attributes[0].Description : value.ToString();
    }
}

答案 6 :(得分:32)

所以没有扩展功能,如果你正在寻找简单和容易..这就是我做的

<%= Html.DropDownListFor(x => x.CurrentAddress.State, new SelectList(Enum.GetValues(typeof(XXXXX.Sites.YYYY.Models.State))))%>

其中XXXXX.Sites.YYYY.Models.State是一个枚举

可能更好地做辅助功能,但是当时间很短时,这将完成工作。

答案 7 :(得分:22)

扩展Prize和Rune的答案,如果您希望将选择列表项的value属性映射到Enumeration类型的整数值而不是字符串值,请使用以下代码:

public static SelectList ToSelectList<T, TU>(T enumObj) 
    where T : struct
    where TU : struct
{
    if(!typeof(T).IsEnum) throw new ArgumentException("Enum is required.", "enumObj");

    var values = from T e in Enum.GetValues(typeof(T))
                 select new { 
                    Value = (TU)Convert.ChangeType(e, typeof(TU)),
                    Text = e.ToString() 
                 };

    return new SelectList(values, "Value", "Text", enumObj);
}

我们可以将其视为一个对象,然后将其转换为整数以获取未装箱的值,而不是将每个Enumeration值视为一个TEnum对象。

注意: 我还添加了一个泛型类型约束来限制此扩展可用的类型只有结构(Enum的基类型),以及运行时类型验证,它确保传入的结构确实是一个枚举。

更新10/23/12: 为基础类型添加了泛型类型参数,并修复了影响.NET 4 +的非编译问题。

答案 8 :(得分:10)

使用Prize的扩展方法解决获取数字而不是文本的问题。

public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
{
  var values = from TEnum e in Enum.GetValues(typeof(TEnum))
               select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                         , Name = e.ToString() };

  return new SelectList(values, "Id", "Name", enumObj);
}

答案 9 :(得分:10)

我找到的最佳解决方案是将this blogSimon Goldstone's answer合并。

这允许在模型中使用枚举。本质上,我们的想法是使用整数属性和枚举,并模拟整数属性。

然后使用[System.ComponentModel.Description]属性用您的显示文本注释模型,并在视图中使用“EnumDropDownListFor”扩展名。

这使视图和模型都具有可读性和可维护性。

型号:

public enum YesPartialNoEnum
{
    [Description("Yes")]
    Yes,
    [Description("Still undecided")]
    Partial,
    [Description("No")]
    No
}

//........

[Display(Name = "The label for my dropdown list")]
public virtual Nullable<YesPartialNoEnum> CuriousQuestion{ get; set; }
public virtual Nullable<int> CuriousQuestionId
{
    get { return (Nullable<int>)CuriousQuestion; }
    set { CuriousQuestion = (Nullable<YesPartialNoEnum>)value; }
}

查看:

@using MyProject.Extensions
{
//...
    @Html.EnumDropDownListFor(model => model.CuriousQuestion)
//...
}

扩展(直接来自Simon Goldstone's answer,此处包含完整性):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel;
using System.Reflection;
using System.Linq.Expressions;
using System.Web.Mvc.Html;

namespace MyProject.Extensions
{
    //Extension methods must be defined in a static class
    public static class MvcExtensions
    {
        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);
        }
    }
}

答案 10 :(得分:9)

完成这项工作的一种非常简单的方法 - 没有看起来有点过分的所有扩展内容是:

你的枚举:

    public enum SelectedLevel
    {
       Level1,
       Level2,
       Level3,
       Level4
    }

在控制器内部将Enum绑定到List:

    List<SelectedLevel> myLevels = Enum.GetValues(typeof(SelectedLevel)).Cast<SelectedLevel>().ToList();

之后将其扔进ViewBag:

    ViewBag.RequiredLevel = new SelectList(myLevels);

最后只需将其绑定到View:

    @Html.DropDownList("selectedLevel", (SelectList)ViewBag.RequiredLevel, new { @class = "form-control" })

这是迄今为止我找到的最简单的方式,不需要任何扩展或任何疯狂的事情。

更新:请参阅下面的安德鲁评论。

答案 11 :(得分:8)

您希望使用Enum.GetValues

之类的内容

答案 12 :(得分:7)

@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))

答案 13 :(得分:6)

这是符文&amp;奖品答案已更改为使用Enum int值作为ID。

示例枚举:

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

扩展方法:

    public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
    {
        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                     select new { Id = (int)Enum.Parse(typeof(TEnum), e.ToString()), Name = e.ToString() };

        return new SelectList(values, "Id", "Name", (int)Enum.Parse(typeof(TEnum), enumObj.ToString()));
    }

使用样本:

 <%=  Html.DropDownList("MyEnumList", ItemTypes.Game.ToSelectList()) %>

请记住导入包含Extension方法的命名空间

<%@ Import Namespace="MyNamespace.LocationOfExtensionMethod" %>

生成的HTML示例:

<select id="MyEnumList" name="MyEnumList">
    <option value="1">Movie</option>
    <option selected="selected" value="2">Game</option>
    <option value="3">Book </option>
</select>

请注意,用于调用ToSelectList的项目是所选项目。

答案 14 :(得分:5)

现在,MVC 5.1通过@Html.EnumDropDownListFor()

开箱即用,支持此功能

检查以下链接:

https://docs.microsoft.com/en-us/aspnet/mvc/overview/releases/mvc51-release-notes#Enum

根据上述投票,微软花了5年的时间来实现如此需求的功能真是太遗憾了!

答案 15 :(得分:5)

这是Razor的版本:

@{
    var itemTypesList = new List<SelectListItem>();
    itemTypesList.AddRange(Enum.GetValues(typeof(ItemTypes)).Cast<ItemTypes>().Select(
                (item, index) => new SelectListItem
                {
                    Text = item.ToString(),
                    Value = (index).ToString(),
                    Selected = Model.ItemTypeId == index
                }).ToList());
 }


@Html.DropDownList("ItemTypeId", itemTypesList)

答案 16 :(得分:4)

嗯,我参加派对的时间已经很晚了,但是对于它的价值,我在博客上写了这个主题,我创建了一个EnumHelper类,可以很容易地进行转换。

http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%23

在你的控制器中:

//If you don't have an enum value use the type
ViewBag.DropDownList = EnumHelper.SelectListFor<MyEnum>();

//If you do have an enum value use the value (the value will be marked as selected)    
ViewBag.DropDownList = EnumHelper.SelectListFor(MyEnum.MyEnumValue);

在您的视图中

@Html.DropDownList("DropDownList")
@* OR *@
@Html.DropDownListFor(m => m.Property, ViewBag.DropDownList as SelectList, null)

助手类:

public static class EnumHelper
{
    // Get the value of the description attribute if the   
    // enum has one, otherwise use the value.  
    public static string GetDescription<TEnum>(this TEnum value)
    {
        var fi = value.GetType().GetField(value.ToString());

        if (fi != null)
        {
            var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attributes.Length > 0)
            {
                return attributes[0].Description;
            }
        }

        return value.ToString();
    }

    /// <summary>
    /// Build a select list for an enum
    /// </summary>
    public static SelectList SelectListFor<T>() where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Value", "Text");
    }

    /// <summary>
    /// Build a select list for an enum with a particular value selected 
    /// </summary>
    public static SelectList SelectListFor<T>(T selected) where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Text", "Value", selected.ToString());
    }

    private static IEnumerable<SelectListItem> BuildSelectListItems(Type t)
    {
        return Enum.GetValues(t)
                   .Cast<Enum>()
                   .Select(e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() });
    }
}

答案 17 :(得分:4)

基于Simon的答案,类似的方法是从资源文件中获取Enum值,而不是在Enum本身的描述属性中显示。如果您的站点需要使用多种语言进行呈现,并且如果您有一个特定的Enums资源文件,这将非常有用,您可以更进一步,在Enum中只使用Enum值,并通过扩展名引用它们诸如[EnumName] _ [EnumValue]之类的约定 - 最终减少输入!

扩展名如下:

public static IHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> html, Expression<Func<TModel, TEnum>> expression)
{            
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);

    var enumType = Nullable.GetUnderlyingType(metadata.ModelType) ?? metadata.ModelType;

    var enumValues = Enum.GetValues(enumType).Cast<object>();

    var items = from enumValue in enumValues                        
                select new SelectListItem
                {
                    Text = GetResourceValueForEnumValue(enumValue),
                    Value = ((int)enumValue).ToString(),
                    Selected = enumValue.Equals(metadata.Model)
                };


    return html.DropDownListFor(expression, items, string.Empty, null);
}

private static string GetResourceValueForEnumValue<TEnum>(TEnum enumValue)
{
    var key = string.Format("{0}_{1}", enumValue.GetType().Name, enumValue);

    return Enums.ResourceManager.GetString(key) ?? enumValue.ToString();
}

Enums.Resx文件中的资源看起来像 ItemTypes_Movie:电影

我喜欢做的另一件事是,不是直接调用扩展方法,而是用@ Html.EditorFor(x =&gt; x.MyProperty)调用它,或者理想情况下只需要整个表单,在一个整洁的@ Html.EditorForModel()。为此,我将字符串模板更改为如下所示

@using MVCProject.Extensions

@{
    var type = Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType) ?? ViewData.ModelMetadata.ModelType;

    @(typeof (Enum).IsAssignableFrom(type) ? Html.EnumDropDownListFor(x => x) : Html.TextBoxFor(x => x))
}

如果您对此感兴趣,我会在我的博客上提供更详细的答案:

http://paulthecyclist.com/2013/05/24/enum-dropdown/

答案 18 :(得分:3)

我在这个问题上已经很晚了,但是如果您愿意添加Unconstrained Melody NuGet包(Jon Skeet的一个不错的小型库),我只想用一行代码找到一个非常酷的方法。 )。

此解决方案更好,因为:

  1. 它确保(使用泛型类型约束)该值实际上是枚举值(由于无约束旋律)
  2. 避免不必要的拳击(由于Unconstrained Melody)
  3. 它缓存所有描述以避免在每次调用时使用反射(由于无约束旋律)
  4. 它的代码少于其他解决方案!
  5. 所以,以下是实现这一目标的步骤:

    1. 在软件包管理器控制台中,“Install-Package UnconstrainedMelody”
    2. 在模型上添加属性,如下所示:

      //Replace "YourEnum" with the type of your enum
      public IEnumerable<SelectListItem> AllItems
      {
          get
          {
              return Enums.GetValues<YourEnum>().Select(enumValue => new SelectListItem { Value = enumValue.ToString(), Text = enumValue.GetDescription() });
          }
      }
      
    3. 现在您已在模型上公开了ListListItem,您可以使用@ Html.DropDownList或@ Html.DropDownListFor将此属性用作源。

答案 19 :(得分:3)

在.NET Core中,您可以仅使用以下代码:

@Html.DropDownListFor(x => x.Foo, Html.GetEnumSelectList<MyEnum>())

答案 20 :(得分:2)

您还可以在Griffin.MvcContrib中使用我的自定义HtmlHelpers。以下代码:

@Html2.CheckBoxesFor(model => model.InputType) <br />
@Html2.RadioButtonsFor(model => model.InputType) <br />
@Html2.DropdownFor(model => model.InputType) <br />

生成:

enter image description here

https://github.com/jgauffin/griffin.mvccontrib

答案 21 :(得分:2)

这是我的帮助方法版本。 我用这个:

var values = from int e in Enum.GetValues(typeof(TEnum))
             select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };

而不是:

var values = from TEnum e in Enum.GetValues(typeof(TEnum))
           select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                     , Name = e.ToString() };

这是:

public static SelectList ToSelectList<TEnum>(this TEnum self) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum)
        {
            throw new ArgumentException("self must be enum", "self");
        }

        Type t = typeof(TEnum);

        var values = from int e in Enum.GetValues(typeof(TEnum))
                     select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };

        return new SelectList(values, "ID", "Name", self);
    }

答案 22 :(得分:2)

如果要添加本地化支持,只需将s.toString()方法更改为以下内容:

ResourceManager rManager = new ResourceManager(typeof(Resources));
var dayTypes = from OperatorCalendarDay.OperatorDayType s in Enum.GetValues(typeof(OperatorCalendarDay.OperatorDayType))
               select new { ID = s, Name = rManager.GetString(s.ToString()) };

在这里,typeof(Resources)是您要加载的资源,然后您获得本地化的String,如果您的枚举器具有包含多个单词的值,这也很有用。

答案 23 :(得分:2)

我找到了答案here。但是,我的一些枚举具有[Description(...)]属性,因此我修改了代码以提供支持:

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

希望有所帮助。

答案 24 :(得分:2)

此扩展方法的另一个修复 - 当前版本未选择枚举的当前值。我修了最后一行:

public static SelectList ToSelectList<TEnum>(this TEnum enumObj) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                       select new
                       {
                           ID = (int)Enum.Parse(typeof(TEnum), e.ToString()),
                           Name = e.ToString()
                       };


        return new SelectList(values, "ID", "Name", ((int)Enum.Parse(typeof(TEnum), enumObj.ToString())).ToString());
    }

答案 25 :(得分:1)

我最终创建了扩展方法来完成本质上接受的答案。 Gist的后半部分专门针对Enum。

https://gist.github.com/3813767

答案 26 :(得分:1)

@Html.DropdownListFor(model=model->Gender,new List<SelectListItem>
{
 new ListItem{Text="Male",Value="Male"},
 new ListItem{Text="Female",Value="Female"},
 new ListItem{Text="--- Select -----",Value="-----Select ----"}
}
)

答案 27 :(得分:1)

@Html.DropDownListFor(model => model.MaritalStatus, new List<SelectListItem> 
{  

new SelectListItem { Text = "----Select----", Value = "-1" },


new SelectListItem { Text = "Marrid", Value = "M" },


 new SelectListItem { Text = "Single", Value = "S" }

})

答案 28 :(得分:1)

@Simon Goldstone:感谢您的解决方案,它可以完美地应用于我的案例中。唯一的问题是我必须将它翻译成VB。但是现在它已经完成并且为了节省其他人的时间(如果他们需要的话)我把它放在这里:

Imports System.Runtime.CompilerServices
Imports System.ComponentModel
Imports System.Linq.Expressions

Public Module HtmlHelpers
    Private Function GetNonNullableModelType(modelMetadata As ModelMetadata) As Type
        Dim realModelType = modelMetadata.ModelType

        Dim underlyingType = Nullable.GetUnderlyingType(realModelType)

        If Not underlyingType Is Nothing Then
            realModelType = underlyingType
        End If

        Return realModelType
    End Function

    Private ReadOnly SingleEmptyItem() As SelectListItem = {New SelectListItem() With {.Text = "", .Value = ""}}

    Private Function GetEnumDescription(Of TEnum)(value As TEnum) As String
        Dim fi = value.GetType().GetField(value.ToString())

        Dim attributes = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())

        If Not attributes Is Nothing AndAlso attributes.Length > 0 Then
            Return attributes(0).Description
        Else
            Return value.ToString()
        End If
    End Function

    <Extension()>
    Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum))) As MvcHtmlString
        Return EnumDropDownListFor(htmlHelper, expression, Nothing)
    End Function

    <Extension()>
    Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum)), htmlAttributes As Object) As MvcHtmlString
        Dim metaData As ModelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData)
        Dim enumType As Type = GetNonNullableModelType(metaData)
        Dim values As IEnumerable(Of TEnum) = [Enum].GetValues(enumType).Cast(Of TEnum)()

        Dim items As IEnumerable(Of SelectListItem) = From value In values
            Select New SelectListItem With
            {
                .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 Then
            items = SingleEmptyItem.Concat(items)
        End If

        Return htmlHelper.DropDownListFor(expression, items, htmlAttributes)
    End Function
End Module

结束你这样使用它:

@Html.EnumDropDownListFor(Function(model) (model.EnumField))

答案 29 :(得分:1)

这是Martin Faartoft的变体,您可以在其中放置适合本地化的自定义标签。

public static class EnumHtmlHelper
{
    public static SelectList ToSelectList<TEnum>(this TEnum enumObj, Dictionary<int, string> customLabels)
        where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                     select new { Id = e, Name = customLabels.First(x => x.Key == Convert.ToInt32(e)).Value.ToString() };

        return new SelectList(values, "Id", "Name", enumObj);
    }
}

在视图中使用:

@Html.DropDownListFor(m => m.Category, Model.Category.ToSelectList(new Dictionary<int, string>() { 
          { 1, ContactResStrings.FeedbackCategory }, 
          { 2, ContactResStrings.ComplainCategory }, 
          { 3, ContactResStrings.CommentCategory },
          { 4, ContactResStrings.OtherCategory }
      }), new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Category)

答案 30 :(得分:1)

我已完成以下工作并成功运作:

  • 在view.cshtml中:

@model MyModel.cs

@Html.EnumDropDownListFor(m=>m.MyItemType )
  • 在模型中: MyModel.cs
  

public ItemTypes MyItemType { get; set; }

答案 31 :(得分:1)

在MVC4中,我会这样做

@Html.DropDownList("RefType", new SelectList(Enum.GetValues(typeof(WebAPIApp.Models.RefType))), " Select", new { @class = "form-control" })

public enum RefType
    {
        Web = 3,
        API = 4,
        Security = 5,
        FE = 6
    }

    public class Reference
    {
        public int Id { get; set; }
        public RefType RefType { get; set; }
    }

答案 32 :(得分:1)

        ////  ViewModel

        public class RegisterViewModel
          {

        public RegisterViewModel()
          {
              ActionsList = new List<SelectListItem>();
          }

        public IEnumerable<SelectListItem> ActionsList { get; set; }

        public string StudentGrade { get; set; }

           }

       //// Enum Class

        public enum GradeTypes
             {
               A,
               B,
               C,
               D,
               E,
               F,
               G,
               H
            }

         ////Controller action 

           public ActionResult Student()
               {
    RegisterViewModel vm = new RegisterViewModel();
    IEnumerable<GradeTypes> actionTypes = Enum.GetValues(typeof(GradeTypes))
                                         .Cast<GradeTypes>();                  
    vm.ActionsList = from action in actionTypes
                     select new SelectListItem
                     {
                         Text = action.ToString(),
                         Value = action.ToString()
                     };
              return View(vm);
               }

         ////// View Action

   <div class="form-group">
                            <label class="col-lg-2 control-label" for="hobies">Student Grade:</label>
                            <div class="col-lg-10">
                               @Html.DropDownListFor(model => model.StudentGrade, Model.ActionsList, new { @class = "form-control" })
                            </div>

答案 33 :(得分:1)

我想以不同的方式回答这个问题,用户不需要在controllerLinq表达式中执行任何操作。这样......

我有ENUM

public enum AccessLevelEnum
    {
        /// <summary>
        /// The user cannot access
        /// </summary>
        [EnumMember, Description("No Access")]
        NoAccess = 0x0,

        /// <summary>
        /// The user can read the entire record in question
        /// </summary>
        [EnumMember, Description("Read Only")]
        ReadOnly = 0x01,

        /// <summary>
        /// The user can read or write
        /// </summary>
        [EnumMember, Description("Read / Modify")]
        ReadModify = 0x02,

        /// <summary>
        /// User can create new records, modify and read existing ones
        /// </summary>
        [EnumMember, Description("Create / Read / Modify")]
        CreateReadModify = 0x04,

        /// <summary>
        /// User can read, write, or delete
        /// </summary>
        [EnumMember, Description("Create / Read / Modify / Delete")]
        CreateReadModifyDelete = 0x08,

        /*/// <summary>
        /// User can read, write, or delete
        /// </summary>
        [EnumMember, Description("Create / Read / Modify / Delete / Verify / Edit Capture Value")]
        CreateReadModifyDeleteVerify = 0x16*/
    }

现在我只能使用此dropdown创建enum

@Html.DropDownList("accessLevel",new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })

OR

@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })

如果要选择索引,请尝试使用

@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum)) , AccessLevelEnum.NoAccess ),new { @class = "form-control" })

这里我使用AccessLevelEnum.NoAccess作为默认选择下拉列表的额外参数。

答案 34 :(得分:0)

1-创建您的ENUM

public enum LicenseType
{
    xxx = 1,
    yyy = 2
}

2-创建服务类

public class LicenseTypeEnumService
    {

        public static Dictionary<int, string> GetAll()
        {

            var licenseTypes = new Dictionary<int, string>();

            licenseTypes.Add((int)LicenseType.xxx, "xxx");
            licenseTypes.Add((int)LicenseType.yyy, "yyy");

            return licenseTypes;

        }

        public static string GetById(int id)
        {

            var q = (from p in this.GetAll() where p.Key == id select p).Single();
            return q.Value;

        }

    }

3-在控制器中设置ViewBag

var licenseTypes = LicenseTypeEnumService.GetAll();
ViewBag.LicenseTypes = new SelectList(licenseTypes, "Key", "Value");

4-绑定DropDownList

@Html.DropDownList("LicenseType", (SelectList)ViewBag.LicenseTypes)

答案 35 :(得分:-6)

更新 - 我建议使用Rune下面的建议而非此选项!


我认为你想要下面的吐口水:

<select name="blah">
    <option value="1">Movie</option>
    <option value="2">Game</option>
    <option value="3">Book</option>
</select>

您可以使用扩展方法执行以下操作:

public static string DropdownEnum(this System.Web.Mvc.HtmlHelper helper,
                                  Enum values)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    sb.Append("<select name=\"blah\">");
    string[] names = Enum.GetNames(values.GetType());
    foreach(string name in names)
    {
        sb.Append("<option value=\"");
        sb.Append(((int)Enum.Parse(values.GetType(), name)).ToString());
        sb.Append("\">");
        sb.Append(name);
        sb.Append("</option>");
    }
    sb.Append("</select>");
    return sb.ToString();
}

但是这样的事情是不可本地化的(即很难翻译成另一种语言)。

注意:您需要使用枚举实例调用静态方法,即Html.DropdownEnum(ItemTypes.Movie);

可能有一种更优雅的方式,但上述方法确实有效。