ASP.NET MVC DropDownList扩展,实现foreach@Html.DropDownListFor(p=>p.Type,p.Type,TypeItem)
页面数据输入的是一个List<TModel>的时。
用foreach(var item in Models)的时候
其中有Item 类里有Type属性,他们是枚举或是关联其它表的数据
此时要用DropDownList显示出来出来
如 Type: 1-小说;2-散文;3-诗;4-词;
var typeItem = new List<SelectListItem>(){ new SelectListItem(){ Value = "1",Text = "小说" }, new SelectListItem(){ Value = "2",Text = "散文" }, new SelectListItem(){ Value = "3",Text = "诗" }, new SelectListItem(){ Value = "4",Text = "词" }, };
cshtml界面
<table> <tr> <th> 序号 </th> <th> 类型 </th> </tr> foreach(var item in Mode) { <tr> <td> item.id </td> <td> @Html.DropDownListFor(item=>item.Type,typeItem); </td> <td> .... </td> </td> } </table>老是显示第一个,明明将Type传入进去了,可还是不行。
如图所示
后来下载了MVC代码看了一下,原来在获取值的时候没有区分当前Type是
Lambda来至 List<TMode> 还是TModel
如果是TModel的话,传入Type是可以正确显示的
而在用List<TMode>的时候,就不行了
页面会将整个List<TModel>传入到后台去
这样他不知道当前如何去取当前是哪个TModel里Type里的值
于是我就增加了一个扩展,将当前的值,同时传入到后台去
这样就可以很好的显示出来了
将
@Html.DropDownListFor(item=>item.Type,typeItem);
改为
@Html.DropDownListFor(item=>item.Type,item.Type,typeItem);
下面把我写的扩展代码贴出来
个人水平有限
如果有什么不对地方,还望指整
using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Web; using System.Web.Mvc; namespace Photography.CoreUI { /// <summary> /// 下拉框扩展 /// mailto:xiaotuni@gmail.com /// 我的BLOG http://blog.csdn.net/xiaotuni /// </summary> public static class XiaotuniDropDownListExtensions { static string MvcResources_HtmlHelper_MissingSelectData = "Missing Select Data"; static string MvcResources_HtmlHelper_WrongSelectDataType = "Wrong Select Data Type"; static string MvcResources_Common_NullOrEmpty = "Null Or Empty"; /// <summary> /// 创建一个DropDownList控件 /// </summary> /// <typeparam name="TModel">当前数据</typeparam> /// <typeparam name="TProperty">属性</typeparam> /// <param name="htmlHelper"></param> /// <param name="expression">lambda 表达式</param> /// <param name="defaultValue">默认值</param> /// <param name="selectList">DropDownList里的数据</param> /// <returns></returns> public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object defaultValue, IEnumerable<SelectListItem> selectList) { return DropDownListFor(htmlHelper, expression, defaultValue, selectList, null, null); } /// <summary> /// 创建一个DropDownList控件 /// </summary> /// <typeparam name="TModel">当前数据</typeparam> /// <typeparam name="TProperty">属性</typeparam> /// <param name="htmlHelper"></param> /// <param name="expression">lambda 表达式</param> /// <param name="defaultValue">默认值</param> /// <param name="selectList">DropDownList里的数据</param> /// <param name="optionLabel">标签名称</param> /// <param name="htmlAttributes">DorpDownList属性</param> /// <returns></returns> public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object defaultValue, IEnumerable<SelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes) { if (expression == null) { throw new ArgumentNullException("expression"); } string name = ExpressionHelper.GetExpressionText(expression); return SelectInternal(htmlHelper, optionLabel, name, selectList, defaultValue, false, htmlAttributes); } /// <summary> /// 获取选中项数据 /// </summary> /// <param name="htmlHelper"></param> /// <param name="name"></param> /// <returns></returns> static IEnumerable<SelectListItem> GetSelectData(this HtmlHelper htmlHelper, string name) { object o = null; if (htmlHelper.ViewData != null) { o = htmlHelper.ViewData.Eval(name); } if (o == null) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources_HtmlHelper_MissingSelectData, name, "IEnumerable<SelectListItem>")); } IEnumerable<SelectListItem> selectList = o as IEnumerable<SelectListItem>; if (selectList == null) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources_HtmlHelper_WrongSelectDataType, name, o.GetType().FullName, "IEnumerable<SelectListItem>")); } return selectList; } static object GetModelStateValue(HtmlHelper htmlHelper, string key, Type destinationType) { ModelState modelState; if (htmlHelper.ViewContext.ViewData.ModelState.TryGetValue(key, out modelState)) { if (modelState.Value != null) { return modelState.Value.ConvertTo(destinationType, null /* culture */); } } return null; } static string ListItemToOption(SelectListItem item) { TagBuilder builder = new TagBuilder("option") { InnerHtml = HttpUtility.HtmlEncode(item.Text) }; if (item.Value != null) { builder.Attributes["value"] = item.Value; } if (item.Selected) { builder.Attributes["selected"] = "selected"; } return builder.ToString(TagRenderMode.Normal); } /// <summary> /// /// </summary> /// <param name="htmlHelper"></param> /// <param name="optionLabel"></param> /// <param name="name"></param> /// <param name="selectList"></param> /// <param name="selectedValue"></param> /// <param name="allowMultiple"></param> /// <param name="htmlAttributes"></param> /// <returns></returns> static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, string optionLabel, string name, IEnumerable<SelectListItem> selectList, object selectedValue, bool allowMultiple, IDictionary<string, object> htmlAttributes) { string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name); if (String.IsNullOrEmpty(fullName)) { throw new ArgumentException(MvcResources_Common_NullOrEmpty, "name"); } bool usedViewData = false; if (selectList == null) { selectList = htmlHelper.GetSelectData(fullName); usedViewData = true; } object defaultValue = selectedValue != null ? selectedValue : (allowMultiple) ? GetModelStateValue(htmlHelper, fullName, typeof(string[])) : GetModelStateValue(htmlHelper, fullName, typeof(string)); if (!usedViewData) { if (defaultValue == null) { defaultValue = htmlHelper.ViewData.Eval(fullName); } } if (defaultValue != null) { IEnumerable defaultValues = (allowMultiple) ? defaultValue as IEnumerable : new[] { defaultValue }; IEnumerable<string> values = from object value in defaultValues select Convert.ToString(value, CultureInfo.CurrentCulture); HashSet<string> selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase); List<SelectListItem> newSelectList = new List<SelectListItem>(); foreach (SelectListItem item in selectList) { item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text); newSelectList.Add(item); } selectList = newSelectList; } StringBuilder listItemBuilder = new StringBuilder(); if (optionLabel != null) { listItemBuilder.AppendLine(ListItemToOption(new SelectListItem() { Text = optionLabel, Value = String.Empty, Selected = false })); } foreach (SelectListItem item in selectList) { listItemBuilder.AppendLine(ListItemToOption(item)); } TagBuilder tagBuilder = new TagBuilder("select") { InnerHtml = listItemBuilder.ToString() }; tagBuilder.MergeAttributes(htmlAttributes); tagBuilder.MergeAttribute("name", fullName, true /* replaceExisting */); tagBuilder.GenerateId(fullName); if (allowMultiple) { tagBuilder.MergeAttribute("multiple", "multiple"); } ModelState modelState; if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState)) { if (modelState.Errors.Count > 0) { tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName); } } tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name)); return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal)); } } }