在下拉列表中支持optgroup .NET MVC?

继续从这个问题编程创build一个下拉列表我希望我的列表也有几个optgroup列表。 目前这是可能的吗?

我知道我需要将一个selectList传递给dropDownList,但不知道如何将文本,值,optgroup添加到selectList。

我想要最终的结果产生:

 <option value="">Please select</option> <optgroup label="Option A"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> </optgroup> <optgroup label="Option B"> <option value="a">A</option> <option value="b">B</option> <option value="c">C</option> </optgroup> </option> 

仔细查看www.codeplex.com/aspnet上的代码,看起来SelectList和DropDownList扩展方法都不支持在select中使用OptGroup。 看起来您需要编写自己的扩展方法,并扩展SelectListItem以包含分组或在标记中手动生成select。

我的扩展有点复杂,但它有所有重载,原来的DropDownList有。

实际上,我已经创build了它,特别是能够生成组的DropDownList,并被转换成两个连接的select帮助下的jDoubleSelect

 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;using System.Web.Routing; public class GroupedSelectListItem : SelectListItem { public string GroupKey { get; set; } public string GroupName { get; set; } } public static class HtmlHelpers { public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name) { return DropDownListHelper(htmlHelper, name, null, null, null); } public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList) { return DropDownListHelper(htmlHelper, name, selectList, null, null); } public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, string optionLabel) { return DropDownListHelper(htmlHelper, name, null, optionLabel, null); } public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, IDictionary<string, object> htmlAttributes) { return DropDownListHelper(htmlHelper, name, selectList, null, htmlAttributes); } public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, object htmlAttributes) { return DropDownListHelper(htmlHelper, name, selectList, null, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); } public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, string optionLabel) { return DropDownListHelper(htmlHelper, name, selectList, optionLabel, null); } public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes) { return DropDownListHelper(htmlHelper, name, selectList, optionLabel, htmlAttributes); } public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, object htmlAttributes) { return DropDownListHelper(htmlHelper, name, selectList, optionLabel, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); } public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList) { return DropDownGroupListFor(htmlHelper, expression, selectList, null /* optionLabel */, null /* htmlAttributes */); } public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, object htmlAttributes) { return DropDownGroupListFor(htmlHelper, expression, selectList, null /* optionLabel */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); } public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, IDictionary<string, object> htmlAttributes) { return DropDownGroupListFor(htmlHelper, expression, selectList, null /* optionLabel */, htmlAttributes); } public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel) { return DropDownGroupListFor(htmlHelper, expression, selectList, optionLabel, null /* htmlAttributes */); } public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, object htmlAttributes) { return DropDownGroupListFor(htmlHelper, expression, selectList, optionLabel, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); } public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes) { if (expression == null) { throw new ArgumentNullException("expression"); } return DropDownListHelper(htmlHelper, ExpressionHelper.GetExpressionText(expression), selectList, optionLabel, htmlAttributes); } private static MvcHtmlString DropDownListHelper(HtmlHelper htmlHelper, string expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes) { return SelectInternal(htmlHelper, optionLabel, expression, selectList, false /* allowMultiple */, htmlAttributes); } // Helper methods private static IEnumerable<GroupedSelectListItem> 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, "Missing Select Data")); } var selectList = o as IEnumerable<GroupedSelectListItem>; if (selectList == null) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, "Wrong Select DataType")); } return selectList; } internal static string ListItemToOption(GroupedSelectListItem item) { var 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); } private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, string optionLabel, string name, IEnumerable<GroupedSelectListItem> selectList, bool allowMultiple, IDictionary<string, object> htmlAttributes) { name = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name); if (String.IsNullOrEmpty(name)) { throw new ArgumentException("Null Or Empty", "name"); } bool usedViewData = false; // If we got a null selectList, try to use ViewData to get the list of items. if (selectList == null) { selectList = htmlHelper.GetSelectData(name); usedViewData = true; } object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(name, typeof(string[])) : htmlHelper.GetModelStateValue(name, typeof(string)); // If we haven't already used ViewData to get the entire list of items then we need to // use the ViewData-supplied value before using the parameter-supplied value. if (!usedViewData) { if (defaultValue == null) { defaultValue = htmlHelper.ViewData.Eval(name); } } if (defaultValue != null) { var defaultValues = (allowMultiple) ? defaultValue as IEnumerable : new[] { defaultValue }; var values = from object value in defaultValues select Convert.ToString(value, CultureInfo.CurrentCulture); var selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase); var newSelectList = new List<GroupedSelectListItem>(); foreach (var item in selectList) { item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text); newSelectList.Add(item); } selectList = newSelectList; } // Convert each ListItem to an <option> tag var listItemBuilder = new StringBuilder(); // Make optionLabel the first item that gets rendered. if (optionLabel != null) { listItemBuilder.AppendLine(ListItemToOption(new GroupedSelectListItem { Text = optionLabel, Value = String.Empty, Selected = false })); } foreach (var group in selectList.GroupBy(i => i.GroupKey)) { string groupName = selectList.Where(i => i.GroupKey == group.Key).Select(it => it.GroupName).FirstOrDefault(); listItemBuilder.AppendLine(string.Format("<optgroup label=\"{0}\" value=\"{1}\">", groupName, group.Key)); foreach (GroupedSelectListItem item in group) { listItemBuilder.AppendLine(ListItemToOption(item)); } listItemBuilder.AppendLine("</optgroup>"); } var tagBuilder = new TagBuilder("select") { InnerHtml = listItemBuilder.ToString() }; tagBuilder.MergeAttributes(htmlAttributes); tagBuilder.MergeAttribute("name", name, true /* replaceExisting */); tagBuilder.GenerateId(name); if (allowMultiple) { tagBuilder.MergeAttribute("multiple", "multiple"); } // If there are any errors for a named field, we add the css attribute. ModelState modelState; if (htmlHelper.ViewData.ModelState.TryGetValue(name, out modelState)) { if (modelState.Errors.Count > 0) { tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName); } } return MvcHtmlString.Create(tagBuilder.ToString()); } internal static object GetModelStateValue(this HtmlHelper helper, string key, Type destinationType) { ModelState modelState; if (helper.ViewData.ModelState.TryGetValue(key, out modelState)) { if (modelState.Value != null) { return modelState.Value.ConvertTo(destinationType, null /* culture */); } } return null; } } 

这被添加到ASP.Net MVC在版本5.2,现在是内置的。

SelectListItem上的Group属性允许您为每个项目指定一个组:

新的SelectList构造函数还允许您在提供的项目列表中提供包含组标题的字段的名称。

HtmlHelper DropDownList和DropDownListFor方法现在基于项目列表中包含的组生成optgroup元素。

简单!

我只是写一个扩展来做到这一点,看看它:


 using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Routing; namespace System.Web.Mvc.Html { public static class GroupDropListExtensions { public static string GroupDropList(this HtmlHelper helper, string name, IEnumerable<GroupDropListItem> data, string SelectedValue, object htmlAttributes) { if (data == null && helper.ViewData != null) data = helper.ViewData.Eval(name) as IEnumerable<GroupDropListItem>; if (data == null) return string.Empty; var select = new TagBuilder("select"); if (htmlAttributes != null) select.MergeAttributes(new RouteValueDictionary(htmlAttributes)); select.GenerateId(name); var optgroupHtml = new StringBuilder(); var groups = data.ToList(); foreach (var group in data) { var groupTag = new TagBuilder("optgroup"); groupTag.Attributes.Add("label", helper.Encode( group.Name)); var optHtml = new StringBuilder(); foreach (var item in group.Items) { var option = new TagBuilder("option"); option.Attributes.Add("value", helper.Encode(item.Value)); if (SelectedValue != null && item.Value == SelectedValue) option.Attributes.Add("selected", "selected"); option.InnerHtml = helper.Encode(item.Text); optHtml.AppendLine(option.ToString(TagRenderMode.Normal)); } groupTag.InnerHtml = optHtml.ToString(); optgroupHtml.AppendLine(groupTag.ToString(TagRenderMode.Normal)); } select.InnerHtml = optgroupHtml.ToString(); return select.ToString(TagRenderMode.Normal); } } public class GroupDropListItem { public string Name { get; set; } public List<OptionItem> Items { get; set; } } public class OptionItem { public string Text { get; set; } public string Value { get; set; } } } 

数据注释客户端validation丢失?

在回答上述Chrno Love的问题时,增加了Serge Zab的解决scheme – 当在相同的视图中使用下拉集合时,Milimetric修复了MVC3客户端validation属性:

  public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes) { if (expression == null) { throw new ArgumentNullException("expression"); } // fixing clientside validation attributes // http://stackoverflow.com/questions/4799958/asp-net-mvc-3-unobtrusive-client-validation-does-not-work-with-drop-down-lists/8102022#8102022 var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); var mergedAttributes = htmlHelper.GetUnobtrusiveValidationAttributes(ExpressionHelper.GetExpressionText(expression), metadata); if (htmlAttributes != null) { foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(htmlAttributes)) { object value = descriptor.GetValue(htmlAttributes); mergedAttributes.Add(descriptor.Name, value); } } //return DropDownListHelper(htmlHelper, ExpressionHelper.GetExpressionText(expression), selectList, optionLabel, htmlAttributes); return DropDownListHelper(htmlHelper, ExpressionHelper.GetExpressionText(expression), selectList, optionLabel, mergedAttributes); } 

Serge Zab的回答正是我所期待的。 作为一个死硬的VB程序员,我把它移植到这个VB模块:

 'based on Serge Zab's answer on http://stackoverflow.com/questions/607188/support-for-optgroup-in-dropdownlist-net-mvc Imports System.Collections Imports System.Collections.Generic Imports System.Globalization Imports System.Linq Imports System.Linq.Expressions Imports System.Text Imports System.Web Imports System.Web.Mvc Imports System.Web.Routing Public Class GroupedSelectListItem Inherits SelectListItem Public Property GroupKey() As String Get Return m_GroupKey End Get Set(value As String) m_GroupKey = Value End Set End Property Private m_GroupKey As String Public Property GroupName() As String Get Return m_GroupName End Get Set(value As String) m_GroupName = Value End Set End Property Private m_GroupName As String End Class Public Module HtmlHelpers <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String) As MvcHtmlString Return DropDownListHelper(htmlHelper, name, Nothing, Nothing, Nothing) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, selectList As IEnumerable(Of GroupedSelectListItem)) As MvcHtmlString Return DropDownListHelper(htmlHelper, name, selectList, Nothing, Nothing) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, optionLabel As String) As MvcHtmlString Return DropDownListHelper(htmlHelper, name, Nothing, optionLabel, Nothing) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, selectList As IEnumerable(Of GroupedSelectListItem), htmlAttributes As IDictionary(Of String, Object)) As MvcHtmlString Return DropDownListHelper(htmlHelper, name, selectList, Nothing, htmlAttributes) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, selectList As IEnumerable(Of GroupedSelectListItem), htmlAttributes As Object) As MvcHtmlString Return DropDownListHelper(htmlHelper, name, selectList, Nothing, New RouteValueDictionary(htmlAttributes)) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String) As MvcHtmlString Return DropDownListHelper(htmlHelper, name, selectList, optionLabel, Nothing) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String, htmlAttributes As IDictionary(Of String, Object)) As MvcHtmlString Return DropDownListHelper(htmlHelper, name, selectList, optionLabel, htmlAttributes) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String, htmlAttributes As Object) As MvcHtmlString Return DropDownListHelper(htmlHelper, name, selectList, optionLabel, New RouteValueDictionary(htmlAttributes)) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of GroupedSelectListItem)) As MvcHtmlString ' optionLabel ' htmlAttributes Return DropDownGroupListFor(htmlHelper, expression, selectList, Nothing, Nothing) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of GroupedSelectListItem), htmlAttributes As Object) As MvcHtmlString ' optionLabel Return DropDownGroupListFor(htmlHelper, expression, selectList, Nothing, New RouteValueDictionary(htmlAttributes)) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of GroupedSelectListItem), htmlAttributes As IDictionary(Of String, Object)) As MvcHtmlString ' optionLabel Return DropDownGroupListFor(htmlHelper, expression, selectList, Nothing, htmlAttributes) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String) As MvcHtmlString ' htmlAttributes Return DropDownGroupListFor(htmlHelper, expression, selectList, optionLabel, Nothing) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String, htmlAttributes As Object) As MvcHtmlString Return DropDownGroupListFor(htmlHelper, expression, selectList, optionLabel, New RouteValueDictionary(htmlAttributes)) End Function <System.Runtime.CompilerServices.Extension> _ Public Function DropDownGroupListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String, htmlAttributes As IDictionary(Of String, Object)) As MvcHtmlString If expression Is Nothing Then Throw New ArgumentNullException("expression") End If Return DropDownListHelper(htmlHelper, ExpressionHelper.GetExpressionText(expression), selectList, optionLabel, htmlAttributes) End Function Private Function DropDownListHelper(htmlHelper As HtmlHelper, expression As String, selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String, htmlAttributes As IDictionary(Of String, Object)) As MvcHtmlString ' allowMultiple Return SelectInternal(htmlHelper, optionLabel, expression, selectList, False, htmlAttributes) End Function ' Helper methods <System.Runtime.CompilerServices.Extension> _ Private Function GetSelectData(htmlHelper As HtmlHelper, name As String) As IEnumerable(Of GroupedSelectListItem) Dim o As Object = Nothing If htmlHelper.ViewData IsNot Nothing Then o = htmlHelper.ViewData.Eval(name) End If If o Is Nothing Then Throw New InvalidOperationException([String].Format(CultureInfo.CurrentCulture, "Missing Select Data", name, "IEnumerable<GroupedSelectListItem>")) End If Dim selectList As IEnumerable(Of GroupedSelectListItem) = TryCast(o, IEnumerable(Of GroupedSelectListItem)) If selectList Is Nothing Then Throw New InvalidOperationException([String].Format(CultureInfo.CurrentCulture, "Wrong Select DataType", name, o.[GetType]().FullName, "IEnumerable<GroupedSelectListItem>")) End If Return selectList End Function Friend Function ListItemToOption(item As GroupedSelectListItem) As String Dim builder As New TagBuilder("option") With { _ .InnerHtml = HttpUtility.HtmlEncode(item.Text) _ } If item.Value IsNot Nothing Then builder.Attributes("value") = item.Value End If If item.Selected Then builder.Attributes("selected") = "selected" End If Return builder.ToString(TagRenderMode.Normal) End Function <System.Runtime.CompilerServices.Extension> _ Private Function SelectInternal(htmlHelper__1 As HtmlHelper, optionLabel As String, name As String, selectList As IEnumerable(Of GroupedSelectListItem), allowMultiple As Boolean, htmlAttributes As IDictionary(Of String, Object)) As MvcHtmlString name = htmlHelper__1.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name) If [String].IsNullOrEmpty(name) Then Throw New ArgumentException("Null Or Empty", "name") End If Dim usedViewData As Boolean = False ' If we got a null selectList, try to use ViewData to get the list of items. If selectList Is Nothing Then selectList = htmlHelper__1.GetSelectData(name) usedViewData = True End If Dim defaultValue As Object = If((allowMultiple), htmlHelper__1.GetModelStateValue(name, GetType(String())), htmlHelper__1.GetModelStateValue(name, GetType(String))) ' If we haven't already used ViewData to get the entire list of items then we need to ' use the ViewData-supplied value before using the parameter-supplied value. If Not usedViewData Then If defaultValue Is Nothing Then defaultValue = htmlHelper__1.ViewData.Eval(name) End If End If If defaultValue IsNot Nothing Then Dim defaultValues As IEnumerable = If((allowMultiple), TryCast(defaultValue, IEnumerable), New String() {defaultValue}) Dim values As IEnumerable(Of String) = From value In defaultValues Select (Convert.ToString(value, CultureInfo.CurrentCulture)) Dim selectedValues As New HashSet(Of String)(values, StringComparer.OrdinalIgnoreCase) Dim newSelectList As New List(Of GroupedSelectListItem)() For Each item As GroupedSelectListItem In selectList item.Selected = If((item.Value IsNot Nothing), selectedValues.Contains(item.Value), selectedValues.Contains(item.Text)) newSelectList.Add(item) Next selectList = newSelectList End If ' Convert each ListItem to an <option> tag Dim listItemBuilder As New StringBuilder() ' Make optionLabel the first item that gets rendered. If optionLabel IsNot Nothing Then listItemBuilder.AppendLine(ListItemToOption(New GroupedSelectListItem() With { _ .Text = optionLabel, _ .Value = [String].Empty, _ .Selected = False _ })) End If For Each group As Object In selectList.GroupBy(Function(i) i.GroupKey) Dim groupName As String = selectList.Where(Function(i) i.GroupKey = group.Key).[Select](Function(it) it.GroupName).FirstOrDefault() listItemBuilder.AppendLine(String.Format("<optgroup label=""{0}"" value=""{1}"">", groupName, group.Key)) For Each item As GroupedSelectListItem In group listItemBuilder.AppendLine(ListItemToOption(item)) Next listItemBuilder.AppendLine("</optgroup>") Next Dim tagBuilder As New TagBuilder("select") With { _ .InnerHtml = listItemBuilder.ToString() _ } TagBuilder.MergeAttributes(htmlAttributes) ' replaceExisting TagBuilder.MergeAttribute("name", name, True) TagBuilder.GenerateId(name) If allowMultiple Then TagBuilder.MergeAttribute("multiple", "multiple") End If ' If there are any errors for a named field, we add the css attribute. Dim modelState As ModelState = Nothing If htmlHelper__1.ViewData.ModelState.TryGetValue(name, modelState) Then If modelState.Errors.Count > 0 Then TagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName) End If End If Return MvcHtmlString.Create(TagBuilder.ToString()) End Function <System.Runtime.CompilerServices.Extension> _ Friend Function GetModelStateValue(helper As HtmlHelper, key As String, destinationType As Type) As Object Dim modelState As ModelState = Nothing If helper.ViewData.ModelState.TryGetValue(key, modelState) Then If modelState.Value IsNot Nothing Then ' culture Return modelState.Value.ConvertTo(destinationType, Nothing) End If End If Return Nothing End Function End Module 

我一直在尝试@Serge Zab解决scheme,哪个工作正常,但是在不显眼的validation方面有一些麻烦,经过一些检查后我发现问题。

似乎有一些必要的属性遗漏了select元素,如果你想启动Jqueryvalidation,就在你创build了你的TagBuilder

 TagBuilder tagBuilder = new TagBuilder("select"); 

添加这些属性

 tagBuilder.MergeAttribute("data-val", "true",true); tagBuilder.MergeAttribute("data-val-required", "your validation message", true) 

不显眼的validation应该会触发。

在Serge Zab的回答中 ,数据属性(如data_valuename )不会以正确的格式data-valuename

我replace了代码tagBuilder.MergeAttributes(htmlAttributes);SelectInternal方法来这个

 foreach (var htmlAttribute in htmlAttributes) { tagBuilder.MergeAttribute( htmlAttribute.Key.Replace('_', '-'), (string)htmlAttribute.Value ); } 

只需要注意使用Serge的扩展在同一表单上创build多个select列表。 我有问题得到第二个select列表来应用组,当我检查正在生成的HTML,我意识到两个都被给了相同的ID。 要解决这个问题,进入serge的扩展中的SelectInternal函数,并注释掉/删除以下两行:

tagBuilder.MergeAttribute(“name”,name,true / * replaceExisting * /); tagBuilder.GenerateId(名称);

或者,你可以传递唯一的ID到每个(虽然DropDownGroupListFor不采取“string名称”参数,所以你将不得不添加一个重载)

我需要一个解决scheme来处理optgroup的多选,我使用了Serge Zab解决scheme。 我只有两条评论(太长的评论)。

  • 尽pipe他声称,他的解决scheme不支持DropDownListFor的所有现有重载,因为它不支持MultiSelectList或SelectList,通常用在模型中。 但是这并不难。

  • 他的解决scheme不适合我多重select来初始化从模型中select/未select的项目:初始值不受影响。 我刚刚修改了以下方法:

    我们可以看到,我们可以使用静态方法来创build一个静态的静态方法。 }

对此:

 private static MvcHtmlString DropDownListHelper(HtmlHelper htmlHelper, string expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes) { bool allowMultiple = htmlAttributes.ContainsKey("multiple"); return SelectInternal(htmlHelper, optionLabel, expression, selectList, allowMultiple, htmlAttributes); } 

它按预期工作。 当然,必须定义multiple属性:@ Html.DropDownGroupListFor(m => m.Selected,Model.Values,new {multiple =“multiple”})

谢谢Serge的回答。