asp.net-mvc-2 drop-down-menu optgroup

asp.net mvc 2 - Soporte desplegable de Optgroup en MVC-Problemas con el enlace de modelos



asp.net-mvc-2 drop-down-menu (3)

Me pregunto si alguien puede arrojar algo de luz sobre este problema ..

Tengo un menú desplegable de grupo de opciones para seleccionar el origen étnico de una persona; sin embargo, no almacena el valor en el modelo.

ViewModel

[UIHint("EthnicOriginEditorTemplate")] [DisplayName("Question 6: Ethnic Origin")] public int EthnicOrigin { get; set; }

Ayudante: GroupDropList.Cs

using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Mvc; using System.Web.Routing; namespace Public.Helpers { public static class GroupDropListExtensions { public static string GroupDropList(this HtmlHelper helper, string name, IEnumerable<GroupDropListItem> data, int 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 != 0 && 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 int Value { get; set; } } }

Este es mi EditorTemplate

<%@ Import Namespace="Public.Helpers"%> <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<int>"%> <%=Html.GroupDropList("EthnicOrigin", new[] { new GroupDropListItem { Name = "Ethnicity", Items = new List<OptionItem> { new OptionItem {Value = 0, Text = "Please Select"} } }, new GroupDropListItem { Name = "a) White", Items = new List<OptionItem> { new OptionItem {Value = 1, Text = "British"}, new OptionItem {Value = 2, Text = "Irish"}, new OptionItem {Value = 3, Text = "Other White (Please specify below)"} } }, --snip }, Model, null)%>

Y en la vista lo estoy haciendo referencia como:

<%=Html.EditorFor(x => x.EthnicOrigin, "EthnicOriginEditorTemplate")%>

Sin embargo, no está pasando por el valor seleccionado en el modelo ... alguien ha experimentado problemas similares ... muchas gracias de antemano por algunos indicadores.


Su select no tiene un atributo de name y, por lo tanto, cuando envía el formulario, el valor seleccionado no se envía al servidor. Debes agregar un nombre:

select.GenerateId(name); select.MergeAttribute("name", name);


Acabo de cambiar la clase de ayuda para hacer que funcione para MVC 3 y con int nullable. Muchas gracias por la clase, me ahorra mucho tiempo.

public static class GroupDropListExtensions { public static MvcHtmlString GroupDropList(this HtmlHelper helper, string name, IEnumerable<GroupDropListItem> data, int? SelectedValue, object htmlAttributes) { if (data == null && helper.ViewData != null) data = helper.ViewData.Eval(name) as IEnumerable<GroupDropListItem>; if (data == null) return new MvcHtmlString(string.Empty); var select = new TagBuilder("select"); if (htmlAttributes != null) select.MergeAttributes(new RouteValueDictionary(htmlAttributes)); select.GenerateId(name); select.MergeAttribute("name", 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 != 0 && 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 new MvcHtmlString(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 int Value { get; set; } }


Esto se admite de forma nativa utilizando SelectListGroup a partir de ASP.NET MVC 5.2:

var items = new List<SelectListItem>(); var group1 = new SelectListGroup() { Name = "Group 1" }; items.Add(new SelectListItem() { Text = "Item1", Group = group1 });

Luego en MVC, hazlo

@Html.DropDownList("select", items)