Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

ASP.NET Multiple Selection DropDownList Using .NET C#

4.57/5 (5 votes)
17 Mar 2019CPOL3 min read 65.4K   821  
ASP.NET Multiple Selection Drop Down List using C# and ASP.NET

Introduction

User Control or Custom Control that satisfy the requirement of selecting multiple items in the drop down list is not available in .NET. Only ListBox does this work but it occupies large vertical space because of which controls on web page cannot be arranged properly. Also, it takes up valuable space on page. Proper alignment of controls is disturbed. Drop down list is neat and slim. Several solutions available with CheckBox which was out of question as you understand. Drop down lists should have smooth text and not other things.
Some solutions are with JavaScript (or jQuery, AJAX, Node JS, etc.) which have several glitches.

So the need for C# and ASP.NET controls only solution was paramount.

Background

My customer wanted the Multi Select Drop Down List for displaying multiple defects or problems that may be found on hand held devices such as Electronic Ticketing Machine (ETM). I searched the entire net and could not find User Control or Custom Control that satisfied the requirements. There were several solutions available with CheckBox which were out of question. So I decided to write my own.

Using the Code

Steps:

  1. Add New Item and select Web Forms ==> Web Forms User Control
  2. Give name and Press Add button.

Following is the HTML markup, in which three controls, ListBox, LinkButton, and ImageButton are used.

ASP.NET
<%@ Control Language="C#" AutoEventWireup="true" 
    CodeBehind="MultiSelectDropDown.ascx.cs" Inherits="WizDevice.MultiSelectDropDown" %>
<html id="t" runat="server">
    <head>
        <title>Multiselect DorpDownList</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta name="author" content="Nitin Rajurkar" />
        <meta content="False" name="vs_snapToGrid" />
        <meta content="True" name="vs_showGrid" />
        <style>
            .CursorStyle {
                cursor:default;
            }
            .LinkStyle {
                cursor:default;
                color: #000000; 
                text-decoration: none;
            }
            .LinkStyle:hover {
                text-decoration: none;
            }
        </style>
    </head>
    <body>
        <asp:Panel ID="MultiSelect_Panel" runat="server" 
        Height="1px" Width="252px" BackColor="White">
            <table id="MultiSelect_Table" runat="server" style="table-layout:fixed; 
             height:16px; border-color:#cccccc; width:100%; border:groove;">
                <tr id="MultiSelect_TableRow" style="height:12px;" runat="server">
                    <td>
                        <asp:LinkButton ID="MultiSelect_LinkButton" runat="server" 
                         CssClass="LinkStyle" Width="252px" Font-Size="Small" 
                         Font-Names="Arial" BorderColor="Transparent" BorderStyle="None" 
                            Height="12px" ToolTip="" OnClick="MultiSelect_LinkButton_Click">
                        </asp:LinkButton>
                    </td>
                    <td id="MultiSelect_Image" style="padding-right: 0px; padding-left: 0px; 
                     padding-bottom: 0px; padding-top: 0px; width: 16px;" runat="server">
                        <asp:ImageButton ID="MultiSelect_ImageButton" runat="server" 
                         ImageUrl="~/Resources/DropDown.bmp" CssClass="CursorStyle" 
                         OnClick="MultiSelect_ImageButton_Click" />
                    </td>
                </tr>
            </table>
            <div id="MultiSelect_div" style="z-index:9999; position:absolute">
                <asp:ListBox ID="MultiSelect_ListBox" runat="server" 
                 Width="100%" SelectionMode="Multiple"
                    OnSelectedIndexChanged="MultiSelect_ListBox_SelectedIndexChanged" >
              </asp:ListBox>
            </div>
        </asp:Panel>
    </body>
</html>

Here, you may use Label in place of LinkButton but Label does not have click event, but you can add it, if you want. Styles are required to make LinkButton appear as normal Label. Provide id to every control to avoid the error "Error Rendering Control. An unhandled exception has occurred."

In code behind, public properties provided to use the control in web page, e.g., change Width, Height, set display text, set and get selected text, values and items. The used controls, ListBox and LinkButton are also made available to the user. You can create custom events. LostFocus (blur) event is provided so that if the drop down is open (has height > 0), it closes as soon as focus is lost. This is the correct behaviour.

C#
protected void Page_Init(object sender, EventArgs e)
        {
            var OnLostFocus = Page.ClientScript.GetPostBackEventReference
                                   (MultiSelect_ListBox, "OnBlur");
            MultiSelect_ListBox.Attributes.Add("onblur", OnLostFocus);
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                MultiSelect_ListBox.Height = 0;
                if (MultiSelect_ListBox.Items.Count > 0)
                {
                    MultiSelect_LinkButton.Text = ItemText.Text;
                }
                else
                {
                    MultiSelect_LinkButton.Text = string.Empty;
                }
            }
            else
            {
                MultiSelect_LinkButton.Text = SelectedText;
                MultiSelect_LinkButton.ToolTip = SelectedText;
                var ControlObject = Request.Params[Page.postEventSourceID];
                var ControlFeature = Request.Params[Page.postEventArgumentID];
                OnLostFocus(ControlObject, ControlFeature);
            }
        }
         private void OnLostFocus(string ControlName, string ControlProperty)
        {
            if ((ControlName == MultiSelect_ListBox.UniqueID) && (ControlProperty == "OnBlur"))
            {
                MultiSelect_ListBox.Height = 0;
            }
        }

Various Properties of MultiSelect

Following are public properties required for using Multiselect Dropdownlist control:

C#
#region  Public properties
    private string _SelectedItem;
    public double ListWidth
    {
       get
       {
          return MultiSelect_Panel.Width.Value;
       }
       set
       {
          MultiSelect_Panel.Width = (Unit)value;
       }
    }
C#
public ArrayList SelectedValues 
{ 
    get 
    { 
        ArrayList selectedValues = new ArrayList(); 
        foreach (ListItem li in MultiSelect_ListBox.Items) 
        { 
            if (li.Selected) 
            { 
                selectedValues.Add(li.Value); 
            } 
        } 
        return selectedValues; 
     } 
}
C#
public ArrayList SelectedTexts 
{ 
    get 
    { 
        ArrayList selectedTexts = new ArrayList(); 
        foreach (ListItem li in MultiSelect_ListBox.Items) 
        { 
            if (li.Selected) 
            { 
                selectedTexts.Add(li.Text); 
            } 
        } 
        return selectedTexts; 
    } 
}
C#
public string SelectedText 
{ 
    get 
    {
        string UserSelectedText = string.Empty; 
        foreach (ListItem li in MultiSelect_ListBox.Items) 
        { 
            if (li.Selected) 
            {  
                 UserSelectedText += li.Text + ","; 
            } 
        } 
        if (UserSelectedText.Length > 0) 
            UserSelectedText = UserSelectedText.Length > 0 ? 
            UserSelectedText.Substring(0, UserSelectedText.Length - 1) : UserSelectedText; 
            return UserSelectedText; 
    } 
    set 
    { 
        _SelectedItem = value; 
        MultiSelect_LinkButton.Text = _SelectedItem; 
        MultiSelect_LinkButton.ToolTip = _SelectedItem; 
    } 
}
C#
public ArrayList SelectedItems 
{ 
    get 
    {
        ArrayList UserSelectedItems = new ArrayList(); 
        foreach (ListItem li in MultiSelect_ListBox.Items) 
        {
            if (li.Selected) 
            {
                UserSelectedItems.Add(li); 
            }
        }
        return UserSelectedItems; 
    } 
    set 
    { 
        ArrayList UserSelectedItems = value; 
        string SelectedElement = string.Empty;  
        foreach (ListItem li in MultiSelect_ListBox.Items) 
        {
            li.Selected = false; 
        }
        foreach (string ItemElement in UserSelectedItems) 
        {
            ListItem li = MultiSelect_ListBox.Items.FindByText(ItemElement); 
            if (li != null) 
            {
                li.Selected = true; 
                SelectedElement += li.Text + ","; 
            } 
        } 
        if (SelectedElement.Length > 0) 
            SelectedElement = SelectedElement.Length > 0 ? 
            SelectedElement.Substring(0, SelectedElement.Length - 1) : SelectedElement; 
            SelectedText = SelectedElement; 
    } 
}
C#
public ListBox List 
{ 
    get 
    {
        return MultiSelect_ListBox; 
    }
    set
    {
        MultiSelect_ListBox = List; 
    } 
} 
public LinkButton ItemText 
{ 
    get 
    { 
        return MultiSelect_LinkButton; 
    } 
    set 
    { 
        MultiSelect_LinkButton = ItemText; 
    } 
} 
#endregion 
C#
public void Clear() 
{ 
    MultiSelect_ListBox.Items.Clear(); 
}

Events

Clicking on arrow or entire box has toggle effect, i.e., if closed, it opens on clicking and vice versa. For this, click events are provided. Also, SelectedIndexChanged event is also provided.

C#
protected void MultiSelect_ImageButton_Click(object sender, System.Web.UI.ImageClickEventArgs e)
    {
        Unit List_Height = MultiSelect_ListBox.Height;
        if (List_Height.Value == 0.0)
        {
            MultiSelect_ListBox.Height = 160;
        }
        else
        {
            MultiSelect_ListBox.Height = 0;
        }
    }

    protected void MultiSelect_LinkButton_Click(object sender, EventArgs e)
    {
        Unit List_Height = MultiSelect_ListBox.Height;
        if (List_Height.Value == 0.0)
        {
            MultiSelect_ListBox.Height = 160;
        }
        else
        {
            MultiSelect_ListBox.Height = 0;
        }
    }

Usage and Population

For using it in web pages, change the Web.Config appropriately, as given below:

ASP.NET
<pages>
      <controls>
        <add tagPrefix="CC" src="~/MultiSelectDropDown.ascx" tagName="MultiSelect"/>
      </controls>
</pages>

You can use your own tagPrefix and tagName.

Then write the following markup in web page:

XML
<CC:MultiSelect ID="Problems_DropDownList" runat="server"></CC:MultiSelect>

You can populate it by any method. Usually, it is populated from data retrieved from database. To set multiple selection, ArrayList can be prepared with string elements. However, you may have ListItems, in which case change foreach (string ItemElement in SelectedItems) to (ListItem ItemElement in SelectedItems) and appropriately to ListItem li = MultiSelect_ListBox.Items.FindByText(ItemElement.ToString()); as string cannot be converted to ListItem, but vice versa is possible.

In code behind of this web page, populate drop down, may be as follows:

C#
protected void Load_DefectList()
    {
        try
        {
            SqlDataAdapter Defect_SqlDataAdapter =
                 new SqlDataAdapter("Load_DefectList", Dal_Obj.OpenConnection());
            Defect_SqlDataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
            Defect_SqlDataAdapter.SelectCommand.Parameters.AddWithValue
                 ("@LanguageId", Session["LanguageId"]);
            Defect_SqlDataAdapter.SelectCommand.Parameters.AddWithValue
                 ("@HostId", Session["HostId"]);

            DataSet Defect_DataSet = new DataSet();
            Defect_SqlDataAdapter.Fill(Defect_DataSet);
            if (Defect_DataSet.Tables[0].Rows.Count > 0)
            {
                Problems_DropDownList.List.DataTextField =
                          Defect_DataSet.Tables[0].Columns["Defect"].ToString();
                Problems_DropDownList.List.DataValueField =
                          Defect_DataSet.Tables[0].Columns["DefectId"].ToString();
                Problems_DropDownList.List.DataSource = Defect_DataSet.Tables[0];
                Problems_DropDownList.List.DataBind();
            }
        }
        catch (Exception Defect_Exception)
        {
            if (Defect_Exception.Message != null)
            {
                Response.Write("alert('Error encountered while loading conductors.
                                Please contact support.')");
            }
        }
        finally
        {
            Dal_Obj.CloseConnection();
        }
    }

To show that multiple values are already assigned (such as in View or Modify), do as follows:

C#
if (DefectiveDevice_DataSet.Tables[1].Rows.Count > 0)
            {
                ArrayList ReportedDefects = new ArrayList();
                int TotalDefect = DefectiveDevice_DataSet.Tables[1].Rows.Count;
                for (int i = 0; i < DefectiveDevice_DataSet.Tables[1].Rows.Count; i++)
                {
                     ReportedDefects.Add(DefectiveDevice_DataSet.Tables[1].Rows[i]["Defect"]);
                }
                Problems_DropDownList.SelectedItems = ReportedDefects;
            }

By using Table Types (in SQL Server), you can send multiple values in a table to your database either to insert, update or delete. See the attached code. Enjoy using this control.

Points of Interest

Type conversion: strings cannot be converted into ListItems but vice versa is possible.

LostFocus event is not available directly. We are using blur event.

History

This is the first version. I will provide new versions as and when they occur.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)