我正在尝试使用Html。下拉列表扩展方法,但不知道如何与枚举一起使用它。
假设我有一个这样的枚举:
public enum ItemTypes
{
Movie = 1,
Game = 2,
Book = 3
}
我如何去创建一个下拉与这些值使用Html。下拉列表扩展方法?
或者我最好的办法是简单地创建一个for循环并手动创建Html元素?
我正在尝试使用Html。下拉列表扩展方法,但不知道如何与枚举一起使用它。
假设我有一个这样的枚举:
public enum ItemTypes
{
Movie = 1,
Game = 2,
Book = 3
}
我如何去创建一个下拉与这些值使用Html。下拉列表扩展方法?
或者我最好的办法是简单地创建一个for循环并手动创建Html元素?
当前回答
现在这个特性在MVC 5.1中通过@Html.EnumDropDownListFor()得到了开箱即用的支持。
查看以下链接:
https://learn.microsoft.com/en-us/aspnet/mvc/overview/releases/mvc51-release-notes#Enum
根据上面的投票,微软花了5年的时间来实现这样一个如此受欢迎的功能,真是太遗憾了!
其他回答
超文本标记语言DropDownListFor只需要一个IEnumerable,所以Prise的解决方案的替代方案如下。这将允许你简单地写:
@Html.DropDownListFor(m => m.SelectedItemType, Model.SelectedItemType.ToSelectList())
[其中SelectedItemType是ItemTypes类型的模型上的字段,并且您的模型是非空的]
此外,您实际上不需要泛化扩展方法,因为您可以使用enumValue.GetType()而不是typeof(T)。
编辑:集成西蒙的解决方案在这里以及,并包括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();
}
}
一个超级简单的方法来做到这一点-没有所有的扩展似乎过度的东西是:
你的枚举:
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);
最后简单地将它绑定到视图:
@Html.DropDownList("selectedLevel", (SelectList)ViewBag.RequiredLevel, new { @class = "form-control" })
这是迄今为止我发现的最简单的方法,不需要任何扩展或任何疯狂的东西。
更新:见安德鲁斯下面的评论。
你也可以在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
对于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();
使用MyApp。常见的
我找到的最好的解决办法就是把这个博客和西蒙·戈德斯通的答案结合起来。
这允许在模型中使用枚举。从本质上讲,这个想法是使用整数属性和枚举,并模拟整数属性。
然后使用[System.ComponentModel。属性用于用你的显示文本注释模型,并在你的视图中使用“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的回答,为完整起见,此处包含):
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);
}
}
}