views:

401

answers:

1

Is it possible to create a select box containing optgroups with asp:DropDownList in version 1.1 of asp.net?

Similar question has been asked here and elsewhere for newer versions of asp.net with solutions involving ControlAdapters or custom controls like the ones from SharpPieces but all this doesn't seem to be compatible with asp.net 1.1

Would it be the only way to craft the html by hand or are there any controls available capable of rendering select boxes with optgroup tags for this old asp.net version?

A: 

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

    [DefaultProperty("Text"),
     ValidationProperty("SelectedItem"),
     ToolboxData("<{0}:EqualDropDownList runat=server></{0}:EqualDropDownList>"),
     ToolboxBitmap(typeof(EqualDropDownList), "dropdown.BMP")]
    public class EqualDropDownList:DropDownList
    {
/// The field in the datasource which provides values for groups
     /// </summary>
     [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;
      }
     }


     /// <summary>
     /// Render this control to the output parameter specified.
     /// Based on the source code of the original DropDownList method
     /// </summary>
     /// <param name="writer"> The HTML writer to write out to </param>
     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 <= 0)
      {
       return;
      }

      for (int i = 0; i < itemCount; i++)
      {
       ListItem item = items[i];
       itemGroup = item.Attributes["DataGroupField"];
       if (itemGroup != null && itemGroup != curGroup)
       {
        if (curGroup != String.Empty)
        {
         writer.WriteEndTag("optgroup");
         writer.WriteLine();
        }

        curGroup = itemGroup;
        writer.WriteBeginTag("optgroup");
        writer.WriteAttribute("label", curGroup, true);
        writer.Write('>');
        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('>');
       HttpUtility.HtmlEncode(item.Text, writer);
       writer.WriteEndTag("option");
       writer.WriteLine();
      }
      if (curGroup != String.Empty)
      {
       writer.WriteEndTag("optgroup");
       writer.WriteLine();
      }
     }


     /// <summary>
     /// Perform data binding logic that is associated with the control
     /// </summary>
     /// <param name="e">An EventArgs object that contains the event data</param>
     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++;
       }
      }

     }

}

You'll need this class too:

public class Util
    {
     /// <summary>
     /// This is copy of the internal ListControl method
     /// </summary>
     /// <param name="dataSource"></param>
     /// <param name="dataMember"></param>
     /// <returns></returns>
     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) && (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) && (obj2 is IEnumerable))
          {
           return (IEnumerable) obj2;
          }
         }
         throw new HttpException("ListSource_Missing_DataMember");
        }
       }
       if (dataSource is IEnumerable)
       {
        return (IEnumerable) dataSource;
       }
      }
      return null;
     }
    }
Ariel Popovsky