Como posso adicionar grupos de opções na lista suspensa do ASP.NET?

Eu tenho um requisito de agrupar as opções da lista suspensa no controle do servidor suspenso do ASP.NET. Você tem alguma idéia de como abordar a questão? Eu sou novo no ASP.NET.

Minha exigência.

Confira este artigo, eu também precisava da lista DropDown do grupo. . .

ASP.NET DropDownList com suporte a OptionGroup

Uso:

protected void Page_Load(object sender, EventArgs e) { ListItem item1 = new ListItem("Camel", "1"); item1.Attributes["OptionGroup"] = "Mammals"; ListItem item2 = new ListItem("Lion", "2"); item2.Attributes["OptionGroup"] = "Mammals"; ListItem item3 = new ListItem("Whale", "3"); item3.Attributes["OptionGroup"] = "Mammals"; ListItem item4 = new ListItem("Walrus", "4"); item4.Attributes["OptionGroup"] = "Mammals"; ListItem item5 = new ListItem("Velociraptor", "5"); item5.Attributes["OptionGroup"] = "Dinosaurs"; ListItem item6 = new ListItem("Allosaurus", "6"); item6.Attributes["OptionGroup"] = "Dinosaurs"; ListItem item7 = new ListItem("Triceratops", "7"); item7.Attributes["OptionGroup"] = "Dinosaurs"; ListItem item8 = new ListItem("Stegosaurus", "8"); item8.Attributes["OptionGroup"] = "Dinosaurs"; ListItem item9 = new ListItem("Tyrannosaurus", "9"); item9.Attributes["OptionGroup"] = "Dinosaurs"; ddlItems.Items.Add(item1); ddlItems.Items.Add(item2); ddlItems.Items.Add(item3); ddlItems.Items.Add(item4); ddlItems.Items.Add(item5); ddlItems.Items.Add(item6); ddlItems.Items.Add(item7); ddlItems.Items.Add(item8); ddlItems.Items.Add(item9); } 

Eu realmente gosto desta solução do lado do cliente (não precisa de um DropDownList personalizado, mas usa jQuery):

backend

 private void _addSelectItem(DropDownList list, string title, string value, string group = null) { ListItem item = new ListItem(title, value); if (!String.IsNullOrEmpty(group)) { item.Attributes["data-category"] = group; } list.Items.Add(item); } ... _addSelectItem(dropDown, "Option 1", "1"); _addSelectItem(dropDown, "Option 2", "2", "Category"); _addSelectItem(dropDown, "Option 3", "3", "Category"); ... 

cliente

 var groups = {}; $("select option[data-category]").each(function () { groups[$.trim($(this).attr("data-category"))] = true; }); $.each(groups, function (c) { $("select option[data-category='"+c+"']").wrapAll(''); }); 

Isso é antigo, mas desde que eu usei a resposta aceita recentemente, eu queria compartilhar minha experiência com isso. Embora ele forneça a marcação correta, isso causou problemas para mim, especificamente sempre que eu tentei enviar um formulário com qualquer lista suspensa, eu pegava o temido erro “Invalid postback or callback argument”. Depois de googlar como um maníaco, me deparei com este artigo que, em seguida, links para este post . O código que acabei usando foi o seguinte:

  public class DropDownListAdapter : System.Web.UI.WebControls.Adapters.WebControlAdapter { protected override void RenderContents(HtmlTextWriter writer) { var dropDownList = (DropDownList)Control; var items = dropDownList.Items; var groups = (from p in items.OfType() group p by p.Attributes["Group"] into g select new { Label = g.Key, Items = g.ToList() }); foreach (var group in groups) { if (!String.IsNullOrEmpty(group.Label)) { writer.WriteBeginTag("optgroup"); writer.WriteAttribute("label", group.Label); writer.Write(">"); } var count = group.Items.Count(); if (count > 0) { var flag = false; for (var i = 0; i < count; i++) { var item = group.Items[i]; writer.WriteBeginTag("option"); if (item.Selected) { if (flag) { throw new HttpException("Multiple selected items not allowed"); } flag = true; writer.WriteAttribute("selected", "selected"); } if (!item.Enabled) { writer.WriteAttribute("disabled", "true"); } writer.WriteAttribute("value", item.Value, true); if (Page != null) { Page.ClientScript.RegisterForEventValidation(dropDownList.UniqueID, item.Value); } writer.Write('>'); HttpUtility.HtmlEncode(item.Text, writer); writer.WriteEndTag("option"); writer.WriteLine(); } } if (!String.IsNullOrEmpty(group.Label)) { writer.WriteEndTag("optgroup"); } } } } 

Os listitems usados ​​aqui são criados na página de design, e não na página code-behind da seguinte forma:

     

Isso produziu a mesma marcação como a resposta aceita aqui, mas isso não me deu o erro de postback. Espero que isso guarde alguma dor a alguém.

 ----- in .cs ----- List sl = new List(); sl.Add(new SelectListItem() { Text = "My text", Value = "1", Group = new SelectListGroup() { Name = "First Group" } }); sl.Add(new SelectListItem() { Text = "My text 2", Value = "2", Group = new SelectListGroup() { Name = "First Group" } }); var sl1 = new SelectList(sl,"Value","Text","Group.Name",-1); ViewData["MyList"] = sl1; ----- in .cshtml ----- Html.DropDownList("My List", ViewData["MyList"] as SelectList, "-- No Preference --", new { @class = "ui-widget ui-corner-all square_corners searchPageDropdown" })) 

1) Adicione a class do adaptador dropdownlist daqui ao seu projeto

2) Adicione a pasta App_Browsers ao seu projeto (clique com o botão direito em project => Add => Add ASP.NET folder => App_Browsers)

3) Adicione um arquivo de navegador na página App_Browsers e adicione o seguinte código abaixo dentro da tag dos navegadores.

refId = WebKit suporta navegadores Chrome e Safari

4) Então você pode adicionar itens à sua lista suspensa ListItem item1 = new ListItem (“Smith Street”, “1”); item1.Attributes [“OptionGroup”] = “Darwin”;

  ListItem item2 = new ListItem("Mitchel Street", "1"); item2.Attributes["OptionGroup"] = "Darwin"; ListItem item3 = new ListItem("Hunter Street", "2"); item3.Attributes["OptionGroup"] = "Sydney"; ListItem item4 = new ListItem("BroadwaY", "4"); item4.Attributes["OptionGroup"] = "Sydney"; venuedropdown.Items.Add(item1); venuedropdown.Items.Add(item2); venuedropdown.Items.Add(item3); venuedropdown.Items.Add(item4); 

Eu uso esse método, que evita ViewBag e ViewData:

Modelo de exibição:

 public class PageViewModel { public int SelectedDropdownItem { get; set; } public IEnumerable DropdownList { get; set; } } 

Exemplo de modelo de entidade (para este exemplo):

 public class Users { public int Id { get; set; } public string Name { get; set; } public bool IsAdministrator { get; set; } public bool IsDefault { get; set; } } 

Controlador:

 // Get list for the dropdown (this uses db values) var userList = db.Users.ToList(); // Define the Groups var group1 = new SelectListGroup { Name = "Administrators" }; var group2 = new SelectListGroup { Name = "Users" }; // Note - the -1 is needed at the end of this - pre-selected value is determined further down // Note .OrderBy() determines the order in which the groups are displayed in the dropdown var dropdownList = new SelectList(userList.Select(item => new SelectListItem { Text = item.Name, Value = item.Id, // Assign the Group to the item by some appropriate selection method Group = item.IsAdministrator ? group1 : group2 }).OrderBy(a => a.Group.Name).ToList(), "Value", "Text", "Group.Name", -1); // Assign values to ViewModel var viewModel = new PageViewModel { // Assign the pre-selected dropdown value by appropriate selction method (if needed) SelectedDropdownItem = userList.FirstOrDefault(a => a.IsDefault).Id, DropdownList = dropdownList }; 

Visão:

  @Html.DropDownListFor(a => a.SelectedDropdownItem, Model.DropdownList, null, new { @class = "some-class" }) 

Espero que isso ajude alguém a evitar o que aconteceu comigo – muito tempo gasto para encontrar um método fortemente tipado.

Esta pequena melhoria para o lado do cliente da excelente solução da mhu também funciona se houver mais de uma seleção de tags.

Com a versão dele, de fato, cada tag de seleção é preenchida com uma cópia de cada tag de opção de cada tag de seleção

(neste exemplo, .select2 é a class em comum a todas as tags selecionadas)

 function filterUserGroups() { var groups = {}; $("select option[data-category]").each(function () { var sGroup = $.trim($(this).attr("data-category")); groups[sGroup] = true; }); $.each(groups, function (c) { $(".select2").each(function () { $(this).find("option[data-category='" + c + "']").wrapAll(''); }) }); } 

Aqui está o que eu fiz, com apenas jquery, sem alterações no lado do servidor:

 /* Add Option Groups to Note Dropdown */ var $select = $('#<%= DropDownListIDHere.ClientID %>'); var optGroup; $('#<%= DropDownListIDHere.ClientID %> option').each(function () { if ($(this).val() == '<') { /* Opener */ optGroup = $('').attr('label', $(this).text()); } else if ($(this).val() == '>') { /* Closer */ $('').appendTo(optGroup); optGroup.appendTo($select); optGroup = null; } else { /* Normal Item */ if (optGroup) { $('').attr('value', $(this).val()).appendTo(optGroup); } else { $('').attr('value', $(this).val()).appendTo($select); } } $(this).remove(); }); 

Em seguida, basta adicionar itens específicos como abridores e closers com valor da seguinte forma:

      

Super simples, sem necessidade de novos controles, somente segmenta o seleto que você deseja alterar e não exige que todos os itens estejam em um optgroup.

Eu preferi uma solução de script de cliente para evitar as complicações no postback, então resolvi assim. Aqui eu uso um html comum apenas para mostrar em function, mas também funciona com o ASP DropDownList: