下拉列表控制与 S代表asp.net(web表单)?(Dropdownlist control

2019-06-18 13:49发布

任何人都可以推荐asp.net(3.5),可以使选项组DropDownList控件? 谢谢

Answer 1:

我用过去的标准控制,只是增加了一个简单的ControlAdapter它会覆盖默认行为,因此它可能在某些地方呈现<OPTGROUP>秒。 这个伟大的工程,即使你有没有需要特殊的行为,因为附加功能不会碍事控制。

请注意,这是为特定目的而编写的.NET 2.0中,因此它可能不适合你的好,但它至少应该给你一个起点。 此外,你必须把它挂在你的项目中使用.browserfile(见文章结尾的例子)。

'This codes makes the dropdownlist control recognize items with "--"
'for the label or items with an OptionGroup attribute and render them
'as <optgroup> instead of <option>.
Public Class DropDownListAdapter
    Inherits System.Web.UI.WebControls.Adapters.WebControlAdapter

    Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
        Dim list As DropDownList = Me.Control
        Dim currentOptionGroup As String
        Dim renderedOptionGroups As New Generic.List(Of String)

        For Each item As ListItem In list.Items
            Page.ClientScript.RegisterForEventValidation(list.UniqueID, item.Value)
            If item.Attributes("OptionGroup") IsNot Nothing Then
                'The item is part of an option group
                currentOptionGroup = item.Attributes("OptionGroup")
                If Not renderedOptionGroups.Contains(currentOptionGroup) Then
                    'the header was not written- do that first
                    'TODO: make this stack-based, so the same option group can be used more than once in longer select element (check the most-recent stack item instead of anything in the list)
                    If (renderedOptionGroups.Count > 0) Then
                        RenderOptionGroupEndTag(writer) 'need to close previous group
                    End If
                    RenderOptionGroupBeginTag(currentOptionGroup, writer)
                    renderedOptionGroups.Add(currentOptionGroup)
                End If
                RenderListItem(item, writer)
            ElseIf item.Text = "--" Then 'simple separator
                RenderOptionGroupBeginTag("--", writer)
                RenderOptionGroupEndTag(writer)
            Else
                'default behavior: render the list item as normal
                RenderListItem(item, writer)
            End If
        Next item

        If renderedOptionGroups.Count > 0 Then
            RenderOptionGroupEndTag(writer)
        End If
    End Sub

    Private Sub RenderOptionGroupBeginTag(ByVal name As String, ByVal writer As HtmlTextWriter)
        writer.WriteBeginTag("optgroup")
        writer.WriteAttribute("label", name)
        writer.Write(HtmlTextWriter.TagRightChar)
        writer.WriteLine()
    End Sub

    Private Sub RenderOptionGroupEndTag(ByVal writer As HtmlTextWriter)
        writer.WriteEndTag("optgroup")
        writer.WriteLine()
    End Sub

    Private Sub RenderListItem(ByVal item As ListItem, ByVal writer As HtmlTextWriter)
        writer.WriteBeginTag("option")
        writer.WriteAttribute("value", item.Value, True)
        If item.Selected Then
            writer.WriteAttribute("selected", "selected", False)
        End If

        For Each key As String In item.Attributes.Keys
            writer.WriteAttribute(key, item.Attributes(key))
        Next key

        writer.Write(HtmlTextWriter.TagRightChar)
        HttpUtility.HtmlEncode(item.Text, writer)
        writer.WriteEndTag("option")
        writer.WriteLine()
    End Sub
End Class

下面是同一类的C#实现:

/* This codes makes the dropdownlist control recognize items with "--"
 * for the label or items with an OptionGroup attribute and render them
 * as <optgroup> instead of <option>.
 */
public class DropDownListAdapter : WebControlAdapter
{
    protected override void RenderContents(HtmlTextWriter writer)
    {
        //System.Web.HttpContext.Current.Response.Write("here");
        var list = (DropDownList)this.Control;
        string currentOptionGroup;
        var renderedOptionGroups = new List<string>();

        foreach (ListItem item in list.Items)
        {
            Page.ClientScript.RegisterForEventValidation(list.UniqueID, item.Value);
            //Is the item part of an option group?
            if (item.Attributes["OptionGroup"] != null)
            {
                currentOptionGroup = item.Attributes["OptionGroup"];
                //Was the option header already written, then just render the list item
                if (renderedOptionGroups.Contains(currentOptionGroup))
                    RenderListItem(item, writer);
                //The header was not written,do that first
                else
                {
                    //Close previous group
                    if (renderedOptionGroups.Count > 0)
                        RenderOptionGroupEndTag(writer);

                    RenderOptionGroupBeginTag(currentOptionGroup, writer);
                    renderedOptionGroups.Add(currentOptionGroup);
                    RenderListItem(item, writer);
                }
            }
            //Simple separator
            else if (item.Text == "--")
            {
                RenderOptionGroupBeginTag("--", writer);
                RenderOptionGroupEndTag(writer);
            }
            //Default behavior, render the list item as normal
            else
                RenderListItem(item, writer);
        }

        if (renderedOptionGroups.Count > 0)
            RenderOptionGroupEndTag(writer);
    }

    private void RenderOptionGroupBeginTag(string name, HtmlTextWriter writer)
    {
        writer.WriteBeginTag("optgroup");
        writer.WriteAttribute("label", name);
        writer.Write(HtmlTextWriter.TagRightChar);
        writer.WriteLine();
    }
    private void RenderOptionGroupEndTag(HtmlTextWriter writer)
    {
        writer.WriteEndTag("optgroup");
        writer.WriteLine();
    }
    private void RenderListItem(ListItem item, HtmlTextWriter writer)
    {
        writer.WriteBeginTag("option");
        writer.WriteAttribute("value", item.Value, true);
        if (item.Selected)
            writer.WriteAttribute("selected", "selected", false);

        foreach (string key in item.Attributes.Keys)
            writer.WriteAttribute(key, item.Attributes[key]);

        writer.Write(HtmlTextWriter.TagRightChar);
        HttpUtility.HtmlEncode(item.Text, writer);
        writer.WriteEndTag("option");
        writer.WriteLine();
    }
}

我的浏览器中的文件被命名为“App_Browsers文件\ BrowserFile.browser”,看起来像这样:

<!--
    You can find existing browser definitions at
    <windir>\Microsoft.NET\Framework\<ver>\CONFIG\Browsers
-->
<browsers>
   <browser refID="Default">
      <controlAdapters>
        <adapter controlType="System.Web.UI.WebControls.DropDownList" 
               adapterType="DropDownListAdapter" />
      </controlAdapters>
   </browser>
</browsers>


Answer 2:

我已经使用jQuery来实现这个任务。 我首先增加了一新属性为每个ListItem从后端,然后在JQuery中使用的属性wrapAll()方法来创建组...

C#:

foreach (ListItem item in ((DropDownList)sender).Items)
{
    if (System.Int32.Parse(item.Value) < 5)
        item.Attributes.Add("classification", "LessThanFive");
    else
        item.Attributes.Add("classification", "GreaterThanFive");
} 

JQuery的:

$(document).ready(function() {
    //Create groups for dropdown list
    $("select.listsmall option[@classification='LessThanFive']")
        .wrapAll("&lt;optgroup label='Less than five'&gt;");
    $("select.listsmall option[@classification='GreaterThanFive']")
        .wrapAll("&lt;optgroup label='Greater than five'&gt;"); 
});


Answer 3:

由于乔尔! 大家......这里的C#版本,如果你想要的:



using System;
using System.Web.UI.WebControls.Adapters;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Generic;
using System.Web;

//This codes makes the dropdownlist control recognize items with "--"'
//for the label or items with an OptionGroup attribute and render them'
//as  instead of .'
public class DropDownListAdapter : WebControlAdapter
{

    protected override void RenderContents(HtmlTextWriter writer)
    {
        DropDownList list = Control as DropDownList;
        string currentOptionGroup;
        List renderedOptionGroups = new List();

        foreach(ListItem item in list.Items)
        {
            if (item.Attributes["OptionGroup"] != null)
            {
                //'The item is part of an option group'
                currentOptionGroup = item.Attributes["OptionGroup"];
                //'the option header was already written, just render the list item'
                if(renderedOptionGroups.Contains(currentOptionGroup))
                    RenderListItem(item, writer);
                else
                {
                    //the header was not written- do that first'
                    if (renderedOptionGroups.Count > 0)
                        RenderOptionGroupEndTag(writer); //'need to close previous group'
                    RenderOptionGroupBeginTag(currentOptionGroup, writer);
                    renderedOptionGroups.Add(currentOptionGroup);
                    RenderListItem(item, writer);
                }
            }
            else if (item.Text == "--") //simple separator
            {
                RenderOptionGroupBeginTag("--", writer);
                RenderOptionGroupEndTag(writer);
            }
            else
            {
                //default behavior: render the list item as normal'
                RenderListItem(item, writer);
            }
        }

        if(renderedOptionGroups.Count > 0)
            RenderOptionGroupEndTag(writer);
    }

    private void RenderOptionGroupBeginTag(string name, HtmlTextWriter writer)
    {
        writer.WriteBeginTag("optgroup");
        writer.WriteAttribute("label", name);
        writer.Write(HtmlTextWriter.TagRightChar);
        writer.WriteLine();
    }

    private void RenderOptionGroupEndTag(HtmlTextWriter writer)
    {
        writer.WriteEndTag("optgroup");
        writer.WriteLine();
    }

    private void RenderListItem(ListItem item, HtmlTextWriter writer)
    {
        writer.WriteBeginTag("option");
        writer.WriteAttribute("value", item.Value, true);
        if (item.Selected)
            writer.WriteAttribute("selected", "selected", false);


        foreach (string key in item.Attributes.Keys)
            writer.WriteAttribute(key, item.Attributes[key]);

        writer.Write(HtmlTextWriter.TagRightChar);
        HttpUtility.HtmlEncode(item.Text, writer);
        writer.WriteEndTag("option");
        writer.WriteLine();
    }

}





Answer 4:

上面的代码为呈现之前的任何选项的OPTGROUP结束标签,所以选择没有得到缩进应该像他们除了不能正确代表分组的标记。 这里是我的汤姆的代码稍加修改的版本:

    public class ExtendedDropDownList : System.Web.UI.WebControls.DropDownList
{
    public const string OptionGroupTag = "optgroup";
    private const string OptionTag = "option";
    protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
    {
        ListItemCollection items = this.Items;
        int count = items.Count;
        string tag;
        string optgroupLabel;
        if (count > 0)
        {
            bool flag = false;
            string prevOptGroup = null;
            for (int i = 0; i < count; i++)
            {
                tag = OptionTag;
                optgroupLabel = null;
                ListItem item = items[i];
                if (item.Enabled)
                {
                    if (item.Attributes != null && item.Attributes.Count > 0 && item.Attributes[OptionGroupTag] != null)
                    {
                        optgroupLabel = item.Attributes[OptionGroupTag];

                        if (prevOptGroup != optgroupLabel)
                        {
                            if (prevOptGroup != null)
                            {
                                writer.WriteEndTag(OptionGroupTag);
                            }
                            writer.WriteBeginTag(OptionGroupTag);
                            if (!string.IsNullOrEmpty(optgroupLabel))
                            {
                                writer.WriteAttribute("label", optgroupLabel);
                            }
                            writer.Write('>');
                        }
                        item.Attributes.Remove(OptionGroupTag);
                        prevOptGroup = optgroupLabel;
                    }
                    else
                    {
                        if (prevOptGroup != null)
                        {
                            writer.WriteEndTag(OptionGroupTag);
                        }
                        prevOptGroup = null;
                    }

                    writer.WriteBeginTag(tag);
                    if (item.Selected)
                    {
                        if (flag)
                        {
                            this.VerifyMultiSelect();
                        }
                        flag = true;
                        writer.WriteAttribute("selected", "selected");
                    }
                    writer.WriteAttribute("value", item.Value, true);
                    if (item.Attributes != null && item.Attributes.Count > 0)
                    {
                        item.Attributes.Render(writer);
                    }
                    if (optgroupLabel != null)
                    {
                        item.Attributes.Add(OptionGroupTag, optgroupLabel);
                    }
                    if (this.Page != null)
                    {
                        this.Page.ClientScript.RegisterForEventValidation(this.UniqueID, item.Value);
                    }

                    writer.Write('>');
                    HttpUtility.HtmlEncode(item.Text, writer);
                    writer.WriteEndTag(tag);
                    writer.WriteLine();
                    if (i == count - 1)
                    {
                        if (prevOptGroup != null)
                        {
                            writer.WriteEndTag(OptionGroupTag);
                        }
                    }
                }
            }
        }
    }

    protected override object SaveViewState()
    {
        object[] state = new object[this.Items.Count + 1];
        object baseState = base.SaveViewState();
        state[0] = baseState;
        bool itemHasAttributes = false;

        for (int i = 0; i < this.Items.Count; i++)
        {
            if (this.Items[i].Attributes.Count > 0)
            {
                itemHasAttributes = true;
                object[] attributes = new object[this.Items[i].Attributes.Count * 2];
                int k = 0;

                foreach (string key in this.Items[i].Attributes.Keys)
                {
                    attributes[k] = key;
                    k++;
                    attributes[k] = this.Items[i].Attributes[key];
                    k++;
                }
                state[i + 1] = attributes;
            }
        }

        if (itemHasAttributes)
            return state;
        return baseState;
    }

    protected override void LoadViewState(object savedState)
    {
        if (savedState == null)
            return;

        if (!(savedState.GetType().GetElementType() == null) &&
            (savedState.GetType().GetElementType().Equals(typeof(object))))
        {
            object[] state = (object[])savedState;
            base.LoadViewState(state[0]);

            for (int i = 1; i < state.Length; i++)
            {
                if (state[i] != null)
                {
                    object[] attributes = (object[])state[i];
                    for (int k = 0; k < attributes.Length; k += 2)
                    {
                        this.Items[i - 1].Attributes.Add
                            (attributes[k].ToString(), attributes[k + 1].ToString());
                    }
                }
            }
        }
        else
        {
            base.LoadViewState(savedState);
        }
    }
}

使用这样的:

            ListItem item1 = new ListItem("option1");
        item1.Attributes.Add("optgroup", "CatA");
        ListItem item2 = new ListItem("option2");
        item2.Attributes.Add("optgroup", "CatA");
        ListItem item3 = new ListItem("option3");
        item3.Attributes.Add("optgroup", "CatB");
        ListItem item4 = new ListItem("option4");
        item4.Attributes.Add("optgroup", "CatB");
        ListItem item5 = new ListItem("NoOptGroup");

        ddlTest.Items.Add(item1);
        ddlTest.Items.Add(item2);
        ddlTest.Items.Add(item3);
        ddlTest.Items.Add(item4);
        ddlTest.Items.Add(item5);

和这里的生成的标记(缩进为便于观察):

 <select name="ddlTest" id="Select1">
    <optgroup label="CatA">
        <option selected="selected" value="option1">option1</option>
        <option value="option2">option2</option>
    </optgroup>
    <optgroup label="CatB">
        <option value="option3">option3</option>
        <option value="option4">option4</option>
    </optgroup>
    <option value="NoOptGroup">NoOptGroup</option>
 </select>


Answer 5:

在CodePlex上的尖锐碎片项目解决了这个(和其他几个)控制的限制。



Answer 6:

我使用反射来看看为什么不支持。 还有为什么。 在列表控件的绘制方法没有条件为有创造OPTGROUP。

protected internal override void RenderContents(HtmlTextWriter writer)
    {
        ListItemCollection items = this.Items;
        int count = items.Count;
        if (count > 0)
        {
            bool flag = false;
            for (int i = 0; i < count; i++)
            {
                ListItem item = items[i];
                if (item.Enabled)
                {
                    writer.WriteBeginTag("option");
                    if (item.Selected)
                    {
                        if (flag)
                        {
                            this.VerifyMultiSelect();
                        }
                        flag = true;
                        writer.WriteAttribute("selected", "selected");
                    }
                    writer.WriteAttribute("value", item.Value, true);
                    if (item.HasAttributes)
                    {
                        item.Attributes.Render(writer);
                    }
                    if (this.Page != null)
                    {
                        this.Page.ClientScript.RegisterForEventValidation(this.UniqueID, item.Value);
                    }
                    writer.Write('>');
                    HttpUtility.HtmlEncode(item.Text, writer);
                    writer.WriteEndTag("option");
                    writer.WriteLine();
                }
            }
        }
    }

所以我创建一个的方法RenderContents的重写我自己的下拉控制。 还有就是我的控制。 是工作的罚款。 我使用完全相同微软的同一代码,只需添加一点点条件,支持具有属性OPTGROUP创建OPTGROUP,而不是一个选项的listItem。

给我一些反馈

public class DropDownListWithOptionGroup : DropDownList
  {
    public const string OptionGroupTag = "optgroup";
    private const string OptionTag = "option";
    protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
    {
      ListItemCollection items = this.Items;
      int count = items.Count;     
      string tag;
      string optgroupLabel;
      if (count > 0)
      {
        bool flag = false;
        for (int i = 0; i < count; i++)
        {
          tag = OptionTag;
          optgroupLabel = null;
          ListItem item = items[i];
          if (item.Enabled)
          {
            if (item.Attributes != null && item.Attributes.Count > 0 && item.Attributes[OptionGroupTag] != null)
            {
              tag = OptionGroupTag;
              optgroupLabel = item.Attributes[OptionGroupTag];
            }           
            writer.WriteBeginTag(tag);
            // NOTE(cboivin): Is optionGroup
            if (!string.IsNullOrEmpty(optgroupLabel))
            {
              writer.WriteAttribute("label", optgroupLabel);
            }
            else
            {
              if (item.Selected)
              {
                if (flag)
                {
                  this.VerifyMultiSelect();
                }
                flag = true;
                writer.WriteAttribute("selected", "selected");
              }
              writer.WriteAttribute("value", item.Value, true);
              if (item.Attributes != null && item.Attributes.Count > 0)
              {
                item.Attributes.Render(writer);
              }
              if (this.Page != null)
              {
                this.Page.ClientScript.RegisterForEventValidation(this.UniqueID, item.Value);
              }
            }
            writer.Write('>');
            HttpUtility.HtmlEncode(item.Text, writer);
            writer.WriteEndTag(tag);
            writer.WriteLine();
          }
        }
      }

    }
  }


Answer 7:

基于上述,我创造了这个控制有工作视图状态的C#版本的职位。

        public const string OptionGroupTag = "optgroup";
    private const string OptionTag = "option";
    protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
    {
        ListItemCollection items = this.Items;
        int count = items.Count;
        string tag;
        string optgroupLabel;
        if (count > 0)
        {
            bool flag = false;
            for (int i = 0; i < count; i++)
            {
                tag = OptionTag;
                optgroupLabel = null;
                ListItem item = items[i];
                if (item.Enabled)
                {
                    if (item.Attributes != null && item.Attributes.Count > 0 && item.Attributes[OptionGroupTag] != null)
                    {
                        tag = OptionGroupTag;
                        optgroupLabel = item.Attributes[OptionGroupTag];
                    }
                    writer.WriteBeginTag(tag);
                    // NOTE(cboivin): Is optionGroup
                    if (!string.IsNullOrEmpty(optgroupLabel))
                    {
                        writer.WriteAttribute("label", optgroupLabel);
                    }
                    else
                    {
                        if (item.Selected)
                        {
                            if (flag)
                            {
                                this.VerifyMultiSelect();
                            }
                            flag = true;
                            writer.WriteAttribute("selected", "selected");
                        }
                        writer.WriteAttribute("value", item.Value, true);
                        if (item.Attributes != null && item.Attributes.Count > 0)
                        {
                            item.Attributes.Render(writer);
                        }
                        if (this.Page != null)
                        {
                            this.Page.ClientScript.RegisterForEventValidation(this.UniqueID, item.Value);
                        }
                    }
                    writer.Write('>');
                    HttpUtility.HtmlEncode(item.Text, writer);
                    writer.WriteEndTag(tag);
                    writer.WriteLine();
                }
            }
        }
    }

        protected override object SaveViewState()
    {
        object[] state = new object[this.Items.Count + 1];
        object baseState = base.SaveViewState();
        state[0] = baseState;
        bool itemHasAttributes = false;

        for (int i = 0; i < this.Items.Count; i++)
        {
            if (this.Items[i].Attributes.Count > 0)
            {
                itemHasAttributes = true;
                object[] attributes = new object[this.Items[i].Attributes.Count * 2];
                int k = 0;

                foreach (string key in this.Items[i].Attributes.Keys)
                {
                    attributes[k] = key;
                    k++;
                    attributes[k] = this.Items[i].Attributes[key];
                    k++;
                }
                state[i + 1] = attributes;
            }
        }

        if (itemHasAttributes)
            return state;
        return baseState;
    }

        protected override void LoadViewState(object savedState)
    {
        if (savedState == null)
            return;

        if (!(savedState.GetType().GetElementType() == null) &&
            (savedState.GetType().GetElementType().Equals(typeof(object))))
        {
            object[] state = (object[])savedState;
            base.LoadViewState(state[0]);

            for (int i = 1; i < state.Length; i++)
            {
                if (state[i] != null)
                {
                    object[] attributes = (object[])state[i];
                    for (int k = 0; k < attributes.Length; k += 2)
                    {
                        this.Items[i - 1].Attributes.Add
                            (attributes[k].ToString(), attributes[k + 1].ToString());
                    }
                }
            }
        }
        else
        {
            base.LoadViewState(savedState);
        }
    }

我希望这可以帮助一些人:-)



Answer 8:

一个更通用的方法来伊尔凡的基于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 + '">');
});


Answer 9:

我做这个使用select和optgroups和该组中的项目内转发外中继器:

<asp:Repeater ID="outerRepeater" runat="server">
    <HeaderTemplate>
        <select id="<%= outerRepeater.ClientID %>">
    </HeaderTemplate>
    <ItemTemplate>
            <optgroup label="<%# Eval("GroupText") %>">
                <asp:Repeater runat="server" DataSource='<%# Eval("Items") %>'>
                    <ItemTemplate>
                        <option value="<%# Eval("Value") %>"><%# Eval("Text") %></option>
                    </ItemTemplate>
                </asp:Repeater>
            </optgroup>
    </ItemTemplate>
    <FooterTemplate>
        </select>
    </FooterTemplate>
</asp:Repeater>

为数据源outerRepeater是一个简单的分组如下:

var data = (from o in thingsToDisplay
            group oby GetAlphaGrouping(o.Name) into g
            orderby g.Key
            select new
            {
                Alpha = g.Key,
                Items = g
            });

和获取alpha分组字符:

private string GetAlphaGrouping(string value)
{
    string firstChar = value.Substring(0, 1).ToUpper();
    int unused;

    if (int.TryParse(firstChar, out unused))
        return "#";

    return firstChar.ToUpper();
}

这不是一个完美的解决方案,但它的工作原理。 正确的解决办法是不再使用的WebForms,但我们MVC代替。 :)



Answer 10:

    // How to use:
    // 1. Create items in a select element or asp:DropDownList control
    // 2. Set value of an option or ListItem to "_group_", those will be converted to optgroups
    // 3. On page onload call createOptGroups(domElement), for example like this:
    //    - var lst = document.getElementById('lst');
    //    - createOptGroups(lst, "_group_");
    // 4. You can change groupMarkerValue to anything, I used "_group_"
    function createOptGroups(lst, groupMarkerValue) {
        // Get an array containing the options
        var childNodes = [];
        for (var i = 0; i < lst.options.length; i++)
            childNodes.push(lst.options[i]);

        // Get the selected element so we can preserve selection
        var selectedIndex = lst.selectedIndex;
        var selectedChild = childNodes[selectedIndex];
        var selectedValue = selectedChild.value;

        // Remove all elements
        while (lst.hasChildNodes())
            lst.removeChild(lst.childNodes[0]);

        // Go through the array of options and convert some into groups
        var group = null;
        for (var i = 0; i < childNodes.length; i++) {
            var node = childNodes[i];
            if (node.value == groupMarkerValue) {
                group = document.createElement("optgroup");
                group.label = node.text;
                group.value = groupMarkerValue;
                lst.appendChild(group);
                continue;
            }

            // Add to group or directly under list
            (group == null ? lst : group).appendChild(node);
        }

        // Preserve selected, no support for multi-selection here, sorry
        selectedChild.selected = true;
    }

经测试在Chrome 16,火狐9和IE8。



Answer 11:

如上,答案重载RenderContents方法做的工作。 你还必须记住要改变视图状态。 使用的UpdatePanel未改变视图状态时,我进入的问题。 这已经从部分采取夏普件项目 。

 Protected Overloads Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
    Dim list As DropDownList = Me

    Dim currentOptionGroup As String
    Dim renderedOptionGroups As New List(Of String)()

    For Each item As ListItem In list.Items
        If item.Attributes("OptionGroup") Is Nothing Then
            RenderListItem(item, writer)
        Else
            currentOptionGroup = item.Attributes("OptionGroup")

            If renderedOptionGroups.Contains(currentOptionGroup) Then
                RenderListItem(item, writer)
            Else
                If renderedOptionGroups.Count > 0 Then
                    RenderOptionGroupEndTag(writer)
                End If

                RenderOptionGroupBeginTag(currentOptionGroup, writer)
                renderedOptionGroups.Add(currentOptionGroup)

                RenderListItem(item, writer)
            End If
        End If
    Next

    If renderedOptionGroups.Count > 0 Then
        RenderOptionGroupEndTag(writer)
    End If
End Sub

Private Sub RenderOptionGroupBeginTag(ByVal name As String, ByVal writer As HtmlTextWriter)
    writer.WriteBeginTag("optgroup")
    writer.WriteAttribute("label", name)
    writer.Write(HtmlTextWriter.TagRightChar)
    writer.WriteLine()
End Sub

Private Sub RenderOptionGroupEndTag(ByVal writer As HtmlTextWriter)
    writer.WriteEndTag("optgroup")
    writer.WriteLine()
End Sub

Private Sub RenderListItem(ByVal item As ListItem, ByVal writer As HtmlTextWriter)
    writer.WriteBeginTag("option")
    writer.WriteAttribute("value", item.Value, True)

    If item.Selected Then
        writer.WriteAttribute("selected", "selected", False)
    End If

    For Each key As String In item.Attributes.Keys
        writer.WriteAttribute(key, item.Attributes(key))
    Next

    writer.Write(HtmlTextWriter.TagRightChar)
    HttpUtility.HtmlEncode(item.Text, writer)
    writer.WriteEndTag("option")
    writer.WriteLine()
End Sub
Protected Overrides Function SaveViewState() As Object
    ' Create an object array with one element for the CheckBoxList's
    ' ViewState contents, and one element for each ListItem in skmCheckBoxList
    Dim state(Me.Items.Count + 1 - 1) As Object 'stupid vb array
    Dim baseState As Object = MyBase.SaveViewState()

    state(0) = baseState
    ' Now, see if we even need to save the view state
    Dim itemHasAttributes As Boolean = False

    For i As Integer = 0 To Me.Items.Count - 1
        If Me.Items(i).Attributes.Count > 0 Then
            itemHasAttributes = True
            ' Create an array of the item's Attribute's keys and values
            Dim attribKV(Me.Items(i).Attributes.Count * 2 - 1) As Object 'stupid vb array
            Dim k As Integer = 0
            For Each key As String In Me.Items(i).Attributes.Keys
                attribKV(k) = key
                k += 1
                attribKV(k) = Me.Items(i).Attributes(key)
                k += 1
            Next
            state(i + 1) = attribKV
        End If
    Next
    ' return either baseState or state, depending on whether or not
    ' any ListItems had attributes
    If (itemHasAttributes) Then
        Return state
    Else
        Return baseState
    End If
End Function


Protected Overrides Sub LoadViewState(ByVal savedState As Object)
    If savedState Is Nothing Then Return
    ' see if savedState is an object or object array
    If Not savedState.GetType.GetElementType() Is Nothing AndAlso savedState.GetType.GetElementType().Equals(GetType(Object)) Then

        ' we have just the base state
        MyBase.LoadViewState(savedState(0))
        'we have an array of items with attributes
        Dim state() As Object = savedState
        MyBase.LoadViewState(state(0))   '/ load the base state
        For i As Integer = 1 To state.Length - 1
            If Not state(i) Is Nothing Then
                ' Load back in the attributes
                Dim attribKV() As Object = state(i)
                For k As Integer = 0 To attribKV.Length - 1 Step +2
                    Me.Items(i - 1).Attributes.Add(attribKV(k).ToString(), attribKV(k + 1).ToString())
                Next
            End If
        Next
    Else
        'load it normal
        MyBase.LoadViewState(savedState)
    End If
End Sub


文章来源: Dropdownlist control with s for asp.net (webforms)?