35

我需要在 ASP.NET 下拉服务器控件中对下拉列表选项进行分组。您对如何解决这个问题有任何想法吗?我是 ASP.NET 的新手。

我的要求。

4

10 回答 10

39

看看这篇文章,我也需要 Group DropDown list 。. .

具有 OptionGroup 支持的 ASP.NET DropDownList

用法 :

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

          }
于 2013-04-23T11:15:30.470 回答
39

我真的很喜欢这个客户端解决方案(不需要自定义 DropDownList,但使用 jQuery):

后端

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");
...

客户

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('<optgroup label="' + c + '">');
});
于 2014-01-31T13:52:01.503 回答
6

这很旧,但由于我最近使用了公认的答案,所以我想分享我的经验。虽然它确实提供了正确的标记,但它给我带来了问题,特别是当我尝试提交带有任何下拉列表的表单时,我会得到可怕的“无效回发或回调参数”错误。在像疯子一样用谷歌搜索之后,我发现了这篇文章,然后链接到了这篇博文。我最终使用的代码是这样的:

    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<ListItem>()
                      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");
            }
        }
    }
}

此处使用的列表项是在设计页面中创建的,而不是在代码隐藏页面中创建的,如下所示:

<asp:ListItem Value="apple" Text="Apple" Group="Fruit"></asp:ListItem>
<asp:ListItem Value="banana" Text="Banana" Group="Fruit"></asp:ListItem>
<asp:ListItem Value="asparagus" Text="Asparagus" Group="Vegetable"></asp:ListItem>
<asp:ListItem Value="eggs" Text="Eggs" Group="Dairy"></asp:ListItem>

这产生了与此处接受的答案相同的标记,但这并没有给我回发错误。我希望这可以减轻一些人的痛苦。

于 2016-01-07T14:44:10.140 回答
2
----- in .cs  -----

List<SelectListItem> sl = new List<SelectListItem>();

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"
                        }))
于 2015-03-26T20:40:06.973 回答
2

1) 将下拉列表适配器类从这里添加到您的项目中

2) 将 App_Browsers 文件夹添加到您的项目中(右键单击项目 => 添加 => 添加 ASP.NET 文件夹 => App_Browsers)

3) 在 App_Browsers 页面中添加一个浏览器文件,并在 browsers 标签内添加以下代码。

<browser refID="WebKit"> <controlAdapters> <adapter controlType="System.Web.UI.WebControls.DropDownList" adapterType="YourAdapterClasse'sNameSPace.DropDownListAdapter" /> </controlAdapters> </browser>

refId = WebKit 支持 chrome 和 safari 浏览器

4) 然后你可以将项目添加到你的下拉列表 ListItem item1 = new ListItem("Smith Street", "1"); item1.Attributes["OptionGroup"] = "达尔文";

            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);
于 2016-05-11T12:13:54.283 回答
1

这是我所做的,仅使用 jquery,没有服务器端更改:

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

然后,您只需将特定项目添加为具有值 < 和 > 的开启者和关闭者,如下所示:

<asp:ListItem Text="Group 1" Value="<" />
<asp:ListItem Text="Thing 1" Value="1111" />
<asp:ListItem Text="Thing 2" Value="2222" />
<asp:ListItem Text="Thing 3" Value="3333" />
<asp:ListItem Text="Group 1" Value=">" />

超级简单,不需要新的控件,只针对要更改的选择,并且不需要每个项目都在一个 optgroup 中。

于 2018-02-28T20:37:13.993 回答
1

我真的很喜欢上面@ScottRFrost 的回答。但是,在撰写本文时,它比我的负载少了两块:

  1. 它没有在我的 UpdatePanel 和
  2. 它没有在回发中保留下拉选择的值。

这是我对他的答案的客户端的扩展:

$(document).ready(function () {

    ddlOptionGrouping();

    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(ddlOptionGrouping);

    function ddlOptionGrouping() {
        /* Add Option Groups to asp:DropdownList */
        var $select = $('#<%= aspDropDownList.ClientID %>');
        var optGroup;
        $('#<%= aspDropDownList.ClientID %> option').each(function () {
            if ($(this).val() == '<') {
                /* Opener */
                optGroup = $('<optGroup>').attr('label', $(this).text());
            } else if ($(this).val() == '>') {
                /* Closer */
                $('</optGroup>').appendTo(optGroup);
                optGroup.appendTo($select);
                optGroup = null;
            } else {
                /* Normal Item */
                let $option = $('<option>' + $(this).text() + '</option>').attr('value', $(this).val());
                if (this.hasAttribute('selected')) {
                    $option.attr('selected', $(this).attr('selected'));
                }
                if (optGroup) {
                    $option.appendTo(optGroup);
                } else {
                    $option.appendTo($select);
                }
            }
            $(this).remove();
        });
    }
});
于 2019-02-23T00:20:40.717 回答
0

我使用这种方法,它避免了 ViewBag 和 ViewData:

查看型号:

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

示例实体模型(对于本示例):

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

控制器:

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

看法:

<!-- If needed, change 'null' to "Please select item" -->
@Html.DropDownListFor(a => a.SelectedDropdownItem, Model.DropdownList, null, new { @class = "some-class" })

希望这可以帮助某人避免发生在我身上的事情-花费太多时间寻找强类型方法。

于 2017-01-27T10:53:06.060 回答
0

如果有多个选择标签,则对mhu 出色解决方案的客户端的这一小幅改进也适用。

实际上,在他的版本中,每个选择标签都会被每个选择标签的每个选项标签的一个副本填充

(在本例中, .select2 是所有选择标签共有的类)

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('<optgroup label="' + c + '">');

        })

    });

}
于 2017-12-13T14:23:29.507 回答
0

我更喜欢客户端脚本解决方案来避免回发的复杂性,所以我像这样解决了它。这里我使用一个普通的 html select 只是为了在函数中显示它,但它也适用于 ASP DropDownList:

<script>
function addOptGrp() {
  var t, p
  for (var i = 0; i < arguments.length; i=i+2) {
    t=arguments[i];
    p=arguments[i+1]-i/2;
    var scripts = document.getElementsByTagName('script');
/* On the next line scripts[scripts.length - 1] is the last script 
   in the page, which by definition will always be the calling script, 
   no matter how many such scripts you have */
    var ddl = scripts[scripts.length - 1].previousElementSibling;
    var og = document.createElement("optgroup");
    og.label = t;
    ddl.add(og,p);
    ddl.selectedIndex = ddl.selectedIndex // needed for UI;
  }
}
</script>

<select style="width:100px;">
  <option>Apple</option>
  <option>Pear</option>
  <option>Banana</option>
  <option>Orange</option>
</select>
<!-- here I just add the option groups in a script that immediately executes. 
     Notice that the script must follow immediately after the select (or DropDownList) -->
<script>addOptGrp(
  'Simple fruits', 0,
  'Very exotic fruits', 3
)</script>
<br><br>

<!-- Here comes another one -->
<select style="width:100px;">
  <option>Red</option>
  <option>Blue</option>
  <option>Yellow</option>
  <option>Green</option>
  <option>Magenta</option>
  <option>White</option>
</select>
<script>addOptGrp(
  'Some colors', 0,
  'Some more colors', 4
)</script>

这个功能满足了我今天的需求。另一天可能需要使用修改后的版本,例如它将普通选项转换为 optgroups,这取决于一些前缀左右。

于 2018-03-29T15:56:20.580 回答