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

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

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

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

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

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

426374 次浏览

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

更新中-我建议使用下面的符文建议,而不是这个选项!


我假设你想要像下面这样的东西吐出来:

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

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

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

事实证明C#3等使这很容易。我有一个名为TaskStatusenum

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

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

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

匿名类型和LINQ使这个更优雅的IMHO。无意冒犯,Ash。:)

对于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();

byusing MyApp.Common

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

编辑:这里也集成了Simon的解决方案,并包含了ToDetption扩展方法。

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

如果您想添加本地化支持,只需将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,如果您的枚举器具有多个单词的值,这也很有用。

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

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

我知道我来晚了,但我想你可能会发现这个变体很有用,因为这个变体还允许你在下拉列表中使用描述性字符串而不是枚举常量。为此,请使用[System. ComponentModel.描述]属性装饰每个枚举条目。

例如:

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-1月23日:微软刚刚发布了MVC 5.1,它现在有一个EnumDropDownListFor功能。遗憾的是,它似乎不尊重[描述]属性,所以上面的代码仍然有效。

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

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

@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))

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

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

生成:

输入图片描述

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

这是Rune&Prise答案更改为使用枚举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()) %>

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

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

生成的超文本标记语言示例:

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

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

我找到的最佳解决方案是将这个博客西蒙·戈德斯通的回答结合起来。

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

然后使用[System. ComponentModel. Detption]属性用显示文本注释模型,并在视图中使用“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)
//...
}

扩展(直接来自西蒙·戈德斯通的回答,此处包含以确保完整性):

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

这是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)

我最终创建了扩展方法来做这里本质上是接受答案的事情。Gist的后半部分专门处理Enum。

我在这方面已经很晚了,但我刚刚找到了一个非常酷的方法,用一行代码来做到这一点,如果你愿意添加无拘无束的旋律 NuGet包(Jon Skeet的一个不错的小库)。

这个解决方案更好,因为:

  1. 它确保(使用泛型类型约束)该值确实是枚举值(由于无约束旋律)
  2. 它避免了不必要的拳击(由于不受约束的旋律)
  3. 它缓存所有的描述,以避免在每次调用时使用反射(由于不受约束的旋律)
  4. 它比其他解决方案的代码少!

因此,以下是使其工作的步骤:

  1. 在软件包管理器控制台中,“Install-Package Un约束的旋律”
  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() });
    }
    }
    

Now that you have the List of SelectListItem exposed on your model, you can use the @Html.DropDownList or @Html.DropDownListFor using this property as the source.

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

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

这是你的模型:

输入图片描述

样品使用:

输入图片描述

生成的UI: 在此处输入图片描述

生成超文本标记语言

输入图片描述

Helper扩展源代码快照:

输入图片描述

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

编辑:这是代码:

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

基于Simon的回答,一种类似的方法是从资源文件中获取要显示的枚举值,而不是在枚举本身的描述属性中。如果您的站点需要以多种语言呈现,并且如果您要为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=>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/

@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 ----"}
}
)
@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" }


})

好吧,我真的迟到了,但值得一提的是,我已经写了一篇关于这个主题的博客,我创建了一个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() });
}
}

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)
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))

现在这个特性在MVC 5.1到@Html.EnumDropDownListFor()中得到了开箱即用的支持

检查以下链接:

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

根据上面的投票,微软花了5年时间才实现了如此受欢迎的功能,这真是太遗憾了!

ASP.NETMVC 5.1中,他们添加了EnumDropDownListFor()助手,因此不需要自定义扩展:

模型

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

查看

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

使用标记助手(ASP.NETMVC 6)

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

我找到了一个答案这里。但是,我的一些枚举具有[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
);
}

希望有帮助。

一个超级简单的方法来完成这件事-没有所有似乎过度的扩展内容是这样的:

您的枚举:

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

在控制器内部,将枚举绑定到列表:

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

这是迄今为止我发现的最简单的方法,不需要任何扩展或任何疯狂的东西。

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

这里有一个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)

我做了以下工作并取得了成功:

  • 在view.cshtml:

@模特MyModel.cs

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

public ItemTypes MyItemType { get; set; }

在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; }
}
        ////  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>

我想以不同的方式回答这个问题,用户不需要在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*/
}

现在我可以使用这个enum简单地创建一个dropdown

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

@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作为默认选择下拉列表的额外参数。

在. NET Core中,您可以使用以下命令:

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