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);
}
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());
}
6
使用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);
}
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
@{
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)
1
这是我的帮助方法版本 . 我用这个:
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);
}
21
这里有一个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(model => model.MaritalStatus, new List<SelectListItem>
{
new SelectListItem { Text = "----Select----", Value = "-1" },
new SelectListItem { Text = "Marrid", Value = "M" },
new SelectListItem { Text = "Single", Value = "S" }
})
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()));
}
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()) };
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 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);
}
}
}
//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);
In your View:
@Html.DropDownList("DropDownList")
@* OR *@
@Html.DropDownListFor(m => m.Property, ViewBag.DropDownList as SelectList, null)
The helper class:
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() });
}
}
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
);
}
希望有所帮助 .
344
@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 ----"}
}
)
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);
@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);
}
}
}
//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() });
}
}
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();
}
}
30 回答
我知道我在这方面已经迟到了,但是你认为这个变种很有用,因为这个变体也允许你在下拉列表中使用描述性字符串而不是枚举常量 . 为此,请使用[System.ComponentModel.Description]属性装饰每个枚举条目 .
例如:
这是我的代码:
然后,您可以在视图中执行此操作:
希望这对你有所帮助!
**编辑2014-JAN-23:微软刚刚发布了MVC 5.1,它现在有一个EnumDropDownListFor功能 . 遗憾的是它似乎不尊重[Description]属性,因此上面的代码仍然有效 . 参见Enum section in Microsoft的MVC 5.1发行说明 .
Update: It does support the Display attribute [Display(Name = "Sample")] though, so one can use that.
[更新 - 只是注意到这一点,代码看起来像这里的代码的扩展版本:https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums/,有几个补充 . 如果是这样,归属似乎是公平的;-)]
因此,如果您正在寻找简单易用的扩展功能..这就是我所做的
其中XXXXX.Sites.YYYY.Models.State是一个枚举
可能更好地做辅助功能,但是当时间很短时,这将完成工作 .
基于Simon的答案,类似的方法是从资源文件中获取Enum值,而不是在Enum本身的描述属性中显示 . 如果您的站点需要使用多种语言进行呈现,并且如果您要为Enums创建特定的资源文件,那么这将非常有用,您可以更进一步,在Enum中只使用枚举值,并通过扩展名引用它们诸如[EnumName] _ [EnumValue]之类的约定 - 最终减少打字!
扩展然后看起来像:
Enums.Resx文件中的资源看起来像ItemTypes_Movie:Film
我喜欢做的另一件事是,不是直接调用扩展方法,而是用@ Html.EditorFor(x => x.MyProperty)调用它,或者理想情况下只需要整个表单,一个整齐的@ Html.EditorForModel() . 为此,我将字符串模板更改为如下所示
如果您对此感兴趣,我会在我的博客上提供更详细的答案:
http://paulthecyclist.com/2013/05/24/enum-dropdown/
在 ASP.NET MVC 5.1 中,他们添加了
EnumDropDownListFor()
助手,因此无需自定义扩展:模型:
视图:
使用Tag Helper(ASP.NET MVC 6):
完成这项工作的一种非常简单的方法 - 没有看起来有点过分的所有扩展内容是这样的:
你的枚举:
在控制器内部将Enum绑定到List:
之后将其抛入ViewBag:
最后,只需将其绑定到View:
这是迄今为止我找到的最简单的方法,不需要任何扩展或任何疯狂的东西 .
UPDATE :请参阅下面的安德鲁斯评论 .
这是一个更好的封装解决方案:
https://www.spicelogic.com/Blog/enum-dropdownlistfor-asp-net-mvc-5
这里说的是你的型号:
Sample Usage:
Generated UI:
And generated HTML
The Helper Extension Source Code snap shot:
您可以从我提供的链接下载示例项目 .
编辑:这是代码:
扩展Prize和Rune的答案,如果您希望将选择列表项的value属性映射到Enumeration类型的整数值,而不是字符串值,请使用以下代码:
我们可以将其视为一个对象,然后将其转换为整数以获取未装箱的值,而不是将每个Enumeration值视为一个TEnum对象 .
Note: 我还添加了一个泛型类型约束来限制此扩展可用的类型只有结构(Enum的基类型),以及运行时类型验证,它确保传入的结构确实是一个枚举 .
Update 10/23/12: 为影响.NET 4的基础类型和修复的非编译问题添加了泛型类型参数 .
此扩展方法的另一个修复 - 当前版本没有选择枚举的当前值 . 我修了最后一行:
使用Prize的扩展方法解决获取数字而不是文本的问题 .
@Simon Goldstone:感谢您的解决方案,它可以完美地应用于我的情况 . 唯一的问题是我必须将其翻译成VB . 但是现在已经完成并且为了节省其他人的时间(如果他们需要的话)我把它放在这里:
结束你这样使用它:
这是Razor的版本:
这是我的帮助方法版本 . 我用这个:
而不是:
这里是:
这里有一个Martin Faartoft变体,您可以在其中放置自定义标签,非常适合本地化 .
在视图中使用:
你想看看像Enum.GetValues这样的东西
这是Rune&Prize答案被更改为使用Enum
int
值作为ID .样本枚举:
扩展方法:
使用样本:
请记住导入包含Extension方法的命名空间
生成的HTML示例:
请注意,用于调用
ToSelectList
的项目是所选项目 .如果要添加本地化支持,只需将s.toString()方法更改为如下所示:
在这里,typeof(Resources)是您要加载的资源,然后您获得本地化的String,如果您的枚举器具有包含多个单词的值,这也很有用 .
我找到的最佳解决方案是将this blog与Simon Goldstone's answer结合起来 .
这允许在模型中使用枚举 . 本质上,我们的想法是使用整数属性以及枚举,并模拟整数属性 .
然后使用[System.ComponentModel.Description]属性为您的显示文本添加模型注释,并在视图中使用“EnumDropDownListFor”扩展名 .
这使得视图和模型都非常易读和可维护 .
模型:
视图:
扩展(直接来自Simon Goldstone's answer,此处包括完整性):
您还可以在Griffin.MvcContrib中使用我的自定义HtmlHelpers . 以下代码:
产生:
https://github.com/jgauffin/griffin.mvccontrib
现在,MVC 5.1中通过
@Html.EnumDropDownListFor()
支持开箱即用的功能检查以下链接:
https://docs.microsoft.com/en-us/aspnet/mvc/overview/releases/mvc51-release-notes#Enum
真是遗憾的是,根据上述投票,微软用了5年的时间来实现这样的功能需求!
好吧,我真的很晚才参加派对,但是为了它的 Value ,我在博客上写了这个主题,我创建了一个
EnumHelper
类,可以很容易地进行转换 .http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%23
In your controller:
In your View:
The helper class:
我找到了答案here . 但是,我的一些枚举有
[Description(...)]
属性,所以我修改了代码以提供支持:希望有所帮助 .
我碰到了同样的问题,找到了这个问题,并认为Ash提供的解决方案不是我想要的;与内置的
Html.DropDownList()
函数相比,必须自己创建HTML意味着更少的灵活性 .原来C#3等让这很容易 . 我有一个名为
TaskStatus
的enum
:这会创建一个好的'
SelectList
,可以像在视图中习惯一样使用:匿名类型和LINQ使这个更优雅的恕我直言 . Ash,没有违法行为 . :)
我做了以下工作并成功运作:
@model MyModel.cs
对于MVC v5.1,使用Html.EnumDropDownListFor
对于MVC v5,请使用EnumHelper
对于MVC 5及更低版本
我将Rune的答案转换为扩展方法:
这允许你写:
by
using MyApp.Common
我最终创建了扩展方法来完成本质上接受的答案 . Gist的后半部分专门针对Enum .
https://gist.github.com/3813767
我在这个问题上已经很晚了,但是如果您乐意添加Unconstrained Melody NuGet包(Jon Skeet的一个漂亮的小型库),我发现用一行代码就可以找到一个非常酷的方法 .
此解决方案更好,因为:
它确保(使用泛型类型约束)该值实际上是枚举值(由于Unconstrained Melody)
它避免了不必要的拳击(由于无约束的旋律)
它缓存所有描述以避免在每次调用时使用反射(由于Unconstrained Melody)
它的代码少于其他解决方案!
所以,这是让这个工作的步骤:
在包管理器控制台中,"Install-Package UnconstrainedMelody"
在模型上添加属性,如下所示:
现在您已在模型上公开了ListListItem,您可以使用@ Html.DropDownList或@ Html.DropDownListFor将此属性用作源 .
Html.DropDownListFor只需要一个IEnumerable,因此Prize解决方案的替代方案如下 . 这将允许您简单地写:
[其中SelectedItemType是类型为ItemTypes的模型上的字段,并且您的模型为非null]
此外,您实际上不需要对扩展方法进行泛化,因为您可以使用enumValue.GetType()而不是typeof(T) .
编辑:这里集成了Simon的解决方案,并包含ToDescription扩展方法 .