Wednesday, 11 January 2012

Group options for Asp.Net DropDownList

Many one of used to create the drop down lists like this

But we can simplify this using optGroup and the o/p follows like this

<select id="DropDownList_OptGroup1" name="DropDownList_OptGroup1">
<option value="0" selected="selected">--Select--</option>
<optgroup label="East India">
<option value="1">Bihar</option>
<option value="2">West Bengal</option>
</optgroup>
<optgroup label="North East India">
<option value="3">Assam</option>
<option value="4">Arunachal Pradesh</option>
</optgroup>
</select>




Asp.net drop down list doesn't support grouping by default how ever  we can do the same in Asp.net by overriding the existed dropdownlist.  Just follow the steps.

1) File -> New -> Project -> select Class Library and rename it as DropDownList_OptGroup


2) Open the Solution Explorer rename the class1.cs with DropDownList_OptGroup.cs




3) Solution Explorer -> Right Click on solution then choose "Add Reference" then from ".Net" tab choose System.Web and click ok.


4) Now open the DropDownList_OptGroup.cs and replace the code with the following








using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;

namespace DropDownList_OptGroup
{
    /// 
    /// Summary description for DropDownList_OptGroup.
    /// 
    [ToolboxData("<{0}:DropDownList_OptGroup runat=server>")]
    public class DropDownList_OptGroup : System.Web.UI.WebControls.DropDownList
    {
        /// 
        /// The field in the datasource which provides values for groups
        /// 
        [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;
            }
        }
        /// 
        /// if a group doesn't has any enabled items,there is no need
        /// to render the group too
        /// 
        /// /// 
        private bool IsGroupHasEnabledItems(string groupName)
        {
            ListItemCollection items = this.Items;
            ListItem item;
            for (int i = 0; i < items.Count; i++)
            {
                item = items[i];
                if (item.Attributes["DataGroupField"].Equals(groupName) && item.Enabled)
                {
                    return true;
                }
            }
            return false;
        }
        /// 
        /// Render this control to the output parameter specified.
        /// Based on the source code of the original DropDownList method
        /// 
        /// The HTML writer to write out to 
        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 = (string)item.Attributes["DataGroupField"];
                if (itemGroup != null && itemGroup != curGroup && IsGroupHasEnabledItems(itemGroup))
                {
                    if (curGroup != String.Empty)
                    {
                        writer.WriteEndTag("optgroup");
                        writer.WriteLine();
                    }

                    curGroup = itemGroup;
                    writer.WriteBeginTag("optgroup");
                    writer.WriteAttribute("label", curGroup, true);
                    writer.Write('>');
                    writer.WriteLine();
                }
                // we don't want to render disabled items
                if (item.Enabled)
                {
                    writer.WriteBeginTag("option");
                    if (item.Selected)
                    {
                        if (bSelected)
                        {
                            throw new HttpException("Cant_Multiselect_In_DropDownList");
                        }
                        bSelected = true;
                        writer.WriteAttribute("selected", "selected", 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();
            }
        }

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

        }

        /// 
        /// This is copy of the internal ListControl method
        /// 
        /// /// /// 
        private 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;
        }
        #region Internal behaviour
        /// Saves the state of the view.
        /// 
        protected override object SaveViewState()
        {
            // Create an object array with one element for the CheckBoxList's'
            // ViewState contents, and one element for each ListItem in skmCheckBoxList
            object[] state = new object[this.Items.Count + 1];

            object baseState = base.SaveViewState();
            state[0] = baseState;

            // Now, see if we even need to save the view state
            bool itemHasAttributes = false;
            for (int i = 0; i < this.Items.Count; i++)
            {
                if (this.Items[i].Attributes.Count > 0)
                {
                    itemHasAttributes = true;

                    // Create an array of the item's Attribute's keys and values
                    object[] attribKV = new object[this.Items[i].Attributes.Count * 2];
                    int k = 0;
                    foreach (string key in this.Items[i].Attributes.Keys)
                    {
                        attribKV[k++] = key;
                        attribKV[k++] = this.Items[i].Attributes[key];
                    }

                    state[i + 1] = attribKV;
                }
            }

            // return either baseState or state, depending on whether or not
            // any ListItems had attributes
            if (itemHasAttributes)
                return state;
            else
                return baseState;
        }

        /// 
        /// Loads the state of the view.
        /// 
        /// State of the saved.
        protected override void LoadViewState(object savedState)
        {
            if (savedState == null) return;

            // see if savedState is an object or object array
            if (savedState is object[])
            {
                // we have an array of items with attributes
                object[] state = (object[])savedState;
                base.LoadViewState(state[0]);   // load the base state

                for (int i = 1; i < state.Length; i++)
                {
                    if (state[i] != null)
                    {
                        // Load back in the attributes
                        object[] attribKV = (object[])state[i];
                        for (int k = 0; k < attribKV.Length; k += 2)
                            this.Items[i - 1].Attributes.Add(attribKV[k].ToString(),
                                                           attribKV[k + 1].ToString());
                    }
                }
            }
            else
                // we have just the base state
                base.LoadViewState(savedState);
        }
        #endregion
    }
}



5) Rebuild the solution

6) Open the solution of your website


7) Toolbox-> Right Click on it and select "Add tab", then write the name of the tab as Extended Controls


8) Right-click on that tab then select "choose items",then from ".Net FrameWork Components" click "Browse", 
then point to the dll that was created by our class library..it's name is "DropDownList_OptGroup.dll".then click OK,then OK for the other dialog, you will notice that our dropdownlist control has been added to the toolbox


9) drag-n-drop DropDownList_OptGroup control


Usage:

Countryid   Country_name        Region
----------  ------------------  ------------------
1           Bihar               East India
2           West Bengal         East India
3           Assam               North East India
4           Arunachal Pradesh   North East India
5           Rajasthan           North India
6           Punjab              North India
7           Jammu and Kashmir   North India
8           Andhra Pradesh      South India
9           Tamilnadu           South India
10          Karnataka           South India
11          Kerala              South India
12          Gujarat             West India
13          Maharashtra         West India



    DataView regionview = ds.Tables[0].DefaultView;
    regionview.Sort = "region asc"; 
    DropDownList_OptGroup1.DataSource = regionview;
    DropDownList_OptGroup1.DataTextField = "country_name";
    DropDownList_OptGroup1.DataValueField = "countryid";
    DropDownList_OptGroup1.DataGroupField = "region";
    DropDownList_OptGroup1.DataBind();
    ListItem li = new ListItem("--Select--", "0");
    li.Attributes.Add("DataGroupField", "");
    DropDownList_OptGroup1.Items.Insert(0, li);



Tag: Asp.net, dropdownlist, optgroup, options, select

14 comments:

  1. Good one!. I used it for my app as a custom control

    Thanks.

    ReplyDelete
  2. Any ideas on how to use this in a gridview?
    I get the type name 'DropDownList_OptGroup1' does not exist in the type 'DropDownList_OptGroup.DropDownList_OptGroup'

    ReplyDelete
  3. This looks promising but I get an "Index was outside the bounds of the array." error when I run it. If I comment out the "DropDownList_OptGroup1.DataGroupField = "region";" then I don't get the error but of course i don't get the groups. So thoughts on that?

    ReplyDelete
  4. Great, And thanks for this beautiful control. :-)

    ReplyDelete
  5. i want to use checkboxes instead of listitems .....how can i get it....

    ReplyDelete
  6. It is working only in Mozilla browser

    ReplyDelete
  7. this custom control helped me alot... love you raja....

    ReplyDelete
  8. Thanks a lot.... Thank You Very Much.............

    ReplyDelete
  9. thanks for your code , it helps me a lot
    please let me know how to get selectd item text and its group heder name in variable

    ReplyDelete
  10. thanks for your code , it helps me a lot
    please let me know how to set the group header Value and how get selectd item text and its group header name and group header value in variable.

    Thank


    ReplyDelete
  11. thanks for your code , it helps me a lot
    please let me know how to set the group header name and group header Value, How to get selectd item text and its group header name and group header value in variable. using asp.net, c#.

    Thanks

    ReplyDelete
  12. thanks for your code , it helps me a lot , but after PostBack the page it selecting First ListItem Every time ..Not selected which i have selected ListItem..

    help me ..how to set the selected ListItem after postback also..

    Thanks.

    ReplyDelete
  13. i want OptGroup inside dropdownlist by wizard and then save the selected value to the database

    ReplyDelete
  14. This comment has been removed by the author.

    ReplyDelete

Parsing JSON w/ @ symbol in it

To read the json response like bellow @ concatenated with attribute                             '{ "@id": 1001, "@name&q...