Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I made one sometime ago and it worked fine at the time. I'll post the relevant pieces so you can build yours (mine had also a readonly mode that rendered a Label instead but you probably don't need it). </p> <pre><code> [DefaultProperty("Text"), ValidationProperty("SelectedItem"), ToolboxData("&lt;{0}:EqualDropDownList runat=server&gt;&lt;/{0}:EqualDropDownList&gt;"), ToolboxBitmap(typeof(EqualDropDownList), "dropdown.BMP")] public class EqualDropDownList:DropDownList { /// The field in the datasource which provides values for groups /// &lt;/summary&gt; [DefaultValue(""), Category("Data")] public virtual string DataGroupField { get { object obj = this.ViewState["DataGroupField"]; if (obj != null) { return (string) obj; } return string.Empty; } set { this.ViewState["DataGroupField"] = value; } } /// &lt;summary&gt; /// Render this control to the output parameter specified. /// Based on the source code of the original DropDownList method /// &lt;/summary&gt; /// &lt;param name="writer"&gt; The HTML writer to write out to &lt;/param&gt; protected override void RenderContents(HtmlTextWriter writer) { ListItemCollection items = this.Items; int itemCount = this.Items.Count; string curGroup = String.Empty; string itemGroup; bool bSelected = false; if (itemCount &lt;= 0) { return; } for (int i = 0; i &lt; itemCount; i++) { ListItem item = items[i]; itemGroup = item.Attributes["DataGroupField"]; if (itemGroup != null &amp;&amp; itemGroup != curGroup) { if (curGroup != String.Empty) { writer.WriteEndTag("optgroup"); writer.WriteLine(); } curGroup = itemGroup; writer.WriteBeginTag("optgroup"); writer.WriteAttribute("label", curGroup, true); writer.Write('&gt;'); writer.WriteLine(); } writer.WriteBeginTag("option"); if (item.Selected) { if (bSelected) { throw new HttpException("Cant_Multiselect_In_DropDownList"); } bSelected = true; writer.WriteAttribute("selected", "selected", false); } foreach (string key in item.Attributes.Keys) { writer.WriteAttribute(key, item.Attributes[key], false); } writer.WriteAttribute("value", item.Value, true); writer.Write('&gt;'); HttpUtility.HtmlEncode(item.Text, writer); writer.WriteEndTag("option"); writer.WriteLine(); } if (curGroup != String.Empty) { writer.WriteEndTag("optgroup"); writer.WriteLine(); } } /// &lt;summary&gt; /// Perform data binding logic that is associated with the control /// &lt;/summary&gt; /// &lt;param name="e"&gt;An EventArgs object that contains the event data&lt;/param&gt; protected override void OnDataBinding(EventArgs e) { // Call base method to bind data base.OnDataBinding(e); if (this.DataGroupField == String.Empty) { return; } // For each Item add the attribute "DataGroupField" with value from the datasource IEnumerable dataSource = Util.GetResolvedDataSource(this.DataSource, this.DataMember); if (dataSource != null) { ListItemCollection items = this.Items; int i = 0; string groupField = this.DataGroupField; foreach (object obj in dataSource) { string groupFieldValue = DataBinder.GetPropertyValue(obj, groupField, null); ListItem item = items[i]; item.Attributes.Add("DataGroupField", groupFieldValue); i++; } } } } </code></pre> <p>You'll need this class too:</p> <pre><code>public class Util { /// &lt;summary&gt; /// This is copy of the internal ListControl method /// &lt;/summary&gt; /// &lt;param name="dataSource"&gt;&lt;/param&gt; /// &lt;param name="dataMember"&gt;&lt;/param&gt; /// &lt;returns&gt;&lt;/returns&gt; public static IEnumerable GetResolvedDataSource(object dataSource, string dataMember) { if (dataSource != null) { IListSource source1 = dataSource as IListSource; if (source1 != null) { IList list1 = source1.GetList(); if (!source1.ContainsListCollection) { return list1; } if ((list1 != null) &amp;&amp; (list1 is ITypedList)) { ITypedList list2 = (ITypedList) list1; PropertyDescriptorCollection collection1 = list2.GetItemProperties(new PropertyDescriptor[0]); if ((collection1 == null) || (collection1.Count == 0)) { throw new HttpException("ListSource_Without_DataMembers"); } PropertyDescriptor descriptor1 = null; if ((dataMember == null) || (dataMember.Length == 0)) { descriptor1 = collection1[0]; } else { descriptor1 = collection1.Find(dataMember, true); } if (descriptor1 != null) { object obj1 = list1[0]; object obj2 = descriptor1.GetValue(obj1); if ((obj2 != null) &amp;&amp; (obj2 is IEnumerable)) { return (IEnumerable) obj2; } } throw new HttpException("ListSource_Missing_DataMember"); } } if (dataSource is IEnumerable) { return (IEnumerable) dataSource; } } return null; } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload