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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/388483/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 01:32:43  来源:igfitidea点击:

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

c#asp.netasp.net-mvc

提问by Kevin Pang

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

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

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.DropDownListextension method?

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

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

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

采纳答案by Martin Faartoft

For MVC v5.1 use Html.EnumDropDownListFor

对于 MVC v5.1 使用 Html.EnumDropDownListFor

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


For MVC v5 use EnumHelper

对于 MVC v5 使用 EnumHelper

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


For MVC 5 and lower

对于 MVC 5 及更低版本

I rolled Rune's answer into an extension method:

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

This allows you to write:

这允许您编写:

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

by using MyApp.Common

经过 using MyApp.Common

回答by Garry Shutler

You want to look at using something like Enum.GetValues

你想看看使用类似的东西 Enum.GetValues

回答by Ash

UPDATED- I would suggest using the suggestion by Rune below rather than this option!

更新- 我建议使用下面 Rune 的建议而不是这个选项!



I assume that you want something like the following spat out:

我假设您想要类似以下内容的内容:

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

which you could do with an extension method something like the following:

您可以使用类似以下的扩展方法来执行此操作:

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

BUTthings like this aren't localisable (i.e. it will be hard to translate into another language).

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

Note: you need to call the static method with an instance of the Enumeration, i.e. Html.DropdownEnum(ItemTypes.Movie);

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

There may be a more elegant way of doing this, but the above does work.

可能有一种更优雅的方法可以做到这一点,但上述方法确实有效。

回答by Rune Jacobsen

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.

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

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

原来 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);

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

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

<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. :)

匿名类型和 LINQ 使这更加优雅恕我直言。无意冒犯,阿什。:)

回答by Nathan Taylor

Expanding on Prise and Rune's answers, if you'd like to have the value attribute of your select list items map to the integer value of the Enumeration type, rather than the string value, use the following code:

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

Instead of treating each Enumeration value as a TEnum object, we can treat it as a object and then cast it to integer to get the unboxed value.

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

Note:I also added a generic type constraint to restrict the types for which this extension is available to only structs (Enum's base type), and a run-time type validation which ensures that the struct passed in is indeed an Enum.

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

Update 10/23/12:Added generic type parameter for underlying type and fixed non-compilation issue affecting .NET 4+.

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

回答by ceedee

To solve the problem of getting the number instead of text using Prise's extension method.

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

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

回答by justabuzz

Another fix to this extension method - the current version didn't select the enum's current value. I fixed the last line:

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

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

回答by Marty Trenouth

So without Extension functions if you are looking for simple and easy.. This is what I did

因此,如果您正在寻找简单易用的功能,则无需扩展功能..这就是我所做的

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

where XXXXX.Sites.YYYY.Models.State is an enum

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

Probably better to do helper function, but when time is short this will get the job done.

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

回答by Zaid Masud

Html.DropDownListFor only requires an IEnumerable, so an alternative to Prise's solution is as follows. This will allow you to simply write:

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

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

[Where SelectedItemType is a field on your model of type ItemTypes, and your model is non-null]

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

Also, you don't really need to genericize the extension method as you can use enumValue.GetType() rather than typeof(T).

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

EDIT: Integrated Simon's solution here as well, and included ToDescription extension method.

编辑:此处也集成了 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();
    }
}

回答by brafales

If you want to add localization support just change the s.toString() method to something like this:

如果您想添加本地化支持,只需将 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()) };

In here the typeof(Resources) is the resource you want to load, and then you get the localized String, also useful if your enumerator has values with multiple words.

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