Asp.net

帶有 <optgroup> 的用於 asp.net (webforms) 的下拉列表控制項?

  • September 24, 2008

誰能推荐一個可以呈現選項組的asp.net(3.5)下拉列表控制項?謝謝

我過去使用過標準控制項,只是為它添加了一個簡單的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 &lt;optgroup&gt; instead of &lt;option&gt;.
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 &gt; 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 &gt; 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 &lt;optgroup&gt; instead of &lt;option&gt;.
*/
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&lt;string&gt;();

       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 &gt; 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 &gt; 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”,如下所示:

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

引用自:https://stackoverflow.com/questions/130020