解决ASP.NET MVC4中使用Html.DropDownListFor显示枚举值默认项问题
从ASP.NET MVC 5开始,Html.DropDownListFor已经提供了对Enum的支持,但在这以前,需要通过帮助方法或扩展方法来让Html.DropDownListFor显示枚举值。
本篇解决在ASP.NET MVC 4 下Html.DropDownListFor显示默认项的问题。
以上,使用Select是通过Html.DropDownListFor来实现的,Select的选项值是从枚举中读出。可以看到,某个枚举值成了默认选项,而我想让"==请选择=="成为Select的默认选项。
在找到解决方法之前,先让问题重现。
有这样的一个枚举。
public enum Status{[EnumDisplayName("启用")]Enabled = 0,[EnumDisplayName("禁用")]Disabled = 1}
有这样的一个View Model的Status属性用来存放枚举的某个值。
public class MyChoice{public short Status { get; set; }}
这里需要帮助方法,能读取枚举的自定义特性EnumDisplayName和枚举值。
首先是自定义特性。
public class EnumDisplayNameAttribute : Attribute{private string _displayName;public EnumDisplayNameAttribute(string displayName){_displayName = displayName;}public string DisplayName{get{return _displayName;}}}
然后,帮助方法使用反射把元数据读取出来,最终得到一个SelectListItem的集合。
/// <summary>/// 把枚举转换成SelectListItem/// </summary>public class EnumExt{/// <summary>/// 获取枚举成员的自定义Attribute的一个属性值/// </summary>/// <param name="e">枚举成员</param>/// <returns></returns>public static string GetEnumDescription(object e){//获取枚举成员的Type对象Type t = e.GetType();//获取Type对象的所有字段FieldInfo[] ms = t.GetFields();//遍历所有字段foreach (FieldInfo f in ms){if (f.Name != e.ToString()){continue;}if (f.IsDefined(typeof(EnumDisplayNameAttribute), true)){return (f.GetCustomAttributes(typeof(EnumDisplayNameAttribute), true)[0] as EnumDisplayNameAttribute).DisplayName;}}return e.ToString();}public static List<SelectListItem> GetSelectList(Type enumType){List<SelectListItem> selectList = new List<SelectListItem>();//selectList.Add(new SelectListItem { Text = "--请选择--", Value = "",Selected = true});foreach (object e in Enum.GetValues(enumType)){selectList.Add(new SelectListItem { Text = GetEnumDescription(e), Value = ((int)e).ToString() });}return selectList;}}
在控制器中,通过ViewData把SelectListItem的集合实例传递到前台。
public ActionResult Index(){ViewData["s"] = EnumExt.GetSelectList(typeof(Status));return View(new MyChoice());}
在视图页中:
@Html.DropDownListFor(m => m.Status,(IEnumerable<SelectListItem>)ViewData["s"],"==请选择==")
现在,就出现了本篇刚开始提到的问题:Select的默认选项是某个枚举值,而不是"==请选择=="。
因为枚举的默认值是0,所以在显示Select的时候,总是把枚举值为0枚举项显示了出来。
既然枚举的默认值是无法改变的,那就让枚举值为0的枚举项的自定义特性显示"==请选择=="。
public enum Status{[EnumDisplayName("==请选择==")]None = 0,[EnumDisplayName("启用")]Enabled = 1,[EnumDisplayName("禁用")]Disabled = 2}
再修改视图页中的部分,Html.DropDownListFor不需要提示文字。
@Html.DropDownListFor(m => m.Status,(IEnumerable<SelectListItem>)ViewData["s"])
最后,得到了想要的效果。