Continuing on from this question programmatically creating a drop down list I would like my list to have several optgroup
lists too. Is this currently possible?
I know I need to pass a selectList to a dropDownList but do not know how to add text, value, optgroup to the selectList.
I want the end 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>
My extension is a bit more complicated, but it has all overloads as original DropDownList has.
Actually I've created it specially to be able to produce DropDownList with groups and to be transformed in to two joined selects with help of 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; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With