Optgroup support in .NET MVC dropdown?

Continuing this question with programmatically creating a drop-down list , I would like for my list to have several optgroup lists. Is this currently possible?

I know that I need to pass selectList to dropDownList, but don’t know how to add text, value, optgroup to selectList.

I want the final result to produce:

 <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> 
+61
drop-down-menu asp.net-mvc
Mar 03 '09 at 16:46
source share
10 answers

Looking through the code www.codeplex.com/aspnet , it seems that neither the SelectList method nor the DropDownList extension method supports the use of OptGroup in the selection. It looks like you need to write your own extension method and extend the SelectListItem to contain the grouping or to generate the selection manually in the markup.

+13
Mar 03 '09 at 17:07
source share

My extension is a bit more complicated, but it has all the overloads, like the original DropDownList.

In fact, I created it specifically to be able to create DropDownList with groups and convert to two contiguous selections using 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; } } 
+91
Nov 22 '10 at 18:26
source share

This was added to ASP.Net MVC version 5.2 and is now integrated.

The Group property on SelectListItem allows you to specify a group for each element:

The new SelectList constructors also let you specify the name of the field containing the group header in the supplied list of items.

Now the HtmlHelper DropDownList and DropDownListFor methods generate optgroup elements based on the groups included in the list of elements.

Easily!

+34
Sep 09 '14 at 13:40
source share

I am just writing extensions for this, see it:




 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; } } } 
+25
May 21 '09 at 9:45
source share

Missing data annotations for customer verification?

In response to the Chrno Love question above, adding to the solution of Serge Zab - Milimetric fix for MVC3 client validation attributes when using a set of drop-down lists in one view:

  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); } 
+1
Mar 07 2018-12-12T00:
source share

Serge Zab's answer was exactly what I was looking for. As a tough VB programmer, I put it in this VB module:

 'based on Serge Zab 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 
+1
Dec 11 '12 at 16:32
source share

I am trying to solve a @Serge Zab solution that works well, but with some problems with unobtrusive validation, after some validation I found a problem.

There seem to be some required attributes missing from the select element if you want the jQuery validation to work right after creating the TagBuilder

 TagBuilder tagBuilder = new TagBuilder("select"); 

Add these attributes

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

and unobtrusive verification should work.

+1
Feb 18
source share

In Serge Zab's answer, data attributes such as data_valuename do not put the data-valuename in the correct form.

I replaced the code tagBuilder.MergeAttributes(htmlAttributes); in SelectInternal on this

 foreach (var htmlAttribute in htmlAttributes) { tagBuilder.MergeAttribute( htmlAttribute.Key.Replace('_', '-'), (string)htmlAttribute.Value ); } 
0
Sep 14 '12 at 20:45
source share

Just a note about using the Serge extension to create more than one select list in the same form. I had problems getting a second selection list for applying groups, and when I examined the generated html, I realized that both have the same identifier. To fix this, go to the SelectInternal function in the serge extension and comment / delete the following two lines:

tagBuilder.MergeAttribute ("name", name, true / * replaceExisting * /); tagBuilder.GenerateId (name);

Alternatively, you can simply pass a unique identifier to each (although DropDownGroupListFor does not accept the string name parameter, so you will need to add an overload)

0
Aug 17 '13 at 19:56
source share

I need a solution for handling multiple selections with optgroup, and I used Serge Zab's solution. I have only two comments about this (too long for a comment).

  • Despite his claims, his solution does not support all existing DropDownListFor overloads, since he does not support MultiSelectList or SelectList, which is often used in models. But it is not difficult to add.

  • His solution did not work for me for multiple selection to initialize selected / not selected elements from the model: the initial values ​​were not affected. I just changed the following method:

    private static MvcHtmlString DropDownListHelper (...) {return SelectInternal (htmlHelper, optionLabel, expression, selectList, false / * allowMultiple * /, htmlAttributes); }

For this:

 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); } 

And it worked as expected. , : @Html.DropDownGroupListFor(m = > m.Selected, Model.Values, new {multiple = "multiple" })

.

0
31 '16 7:49
source share



All Articles