

Introduction
Recently, I was looking for a multiple selection dropdownlist control for my new project. After spending some time researching for it, I decided to put together all my findings in one web user control. This web user control consists of an ASP.NET AJAX HoverMenuExtender, JavaScript, Stylesheet, and a CheckBoxListExCtrl. The final product will work with or without a masterpage, and you can drag and drop more than one instance of the control on to the page. This is not a perfect control, feel free to modify it to tailor your requirements, and share your thoughts. Below is a step by step tutorial on how I have accomplished this. Hope this tutorial will give someone an idea on how to use the ASP.NET AJAX HoverMenuExtender and create a multiple selection dropdownlist.
Before we begin, here is the structure of my project:

Using the Code
This is a user control, just drag and drop. But make sure to include the ScriptManager.
The project includes:
- Default.aspx - this page does not use master page or user controls.
- MS_With_UserControl.aspx - this page uses multiple instances of the user control and no master page.
- MS_With_UserControl_and_Masterpage.aspx - this page uses multiple instances of the user control and a master page.
CheckBoxListExCtrl - How to get the CheckBoxList value using JavaScript?
- The rest of the files are fairly self-explanatory.
CheckBoxListExCtrl
The code is pretty much the same except I have made a few changes to return the text of the selected checkbox. Please see the comments.
string clientID = UniqueID + this.ClientIDSeparator +
repeatIndex.ToString(NumberFormatInfo.InvariantInfo);
writer.WriteBeginTag("input");
writer.WriteAttribute("type", "checkbox");
writer.WriteAttribute("name", UniqueID + this.IdSeparator +
repeatIndex.ToString(NumberFormatInfo.InvariantInfo));
writer.WriteAttribute("id", clientID);
writer.WriteAttribute("value", Items[repeatIndex].Value);
if (Items[repeatIndex].Selected)
writer.WriteAttribute("checked", "checked");
System.Web.UI.AttributeCollection attrs = Items[repeatIndex].Attributes;
foreach (string key in attrs.Keys)
{
writer.WriteAttribute(key, attrs[key]);
}
writer.Write("/>"); writer.Write("<label for="" + clientID + "">");
writer.Write(Items[repeatIndex].Text); writer.Write("</label>");
MultipleSelectionDDLJS.js
Here is the contents of the JavaScript, please read the comments:
var Browser = {
Version: function() {
var version = 999; if (navigator.appVersion.indexOf("MSIE") != -1)
version = parseFloat(navigator.appVersion.split("MSIE")[1]);
return version;
}
}
function showIE6Tooltip(e){
if (navigator.appName=='Microsoft Internet Explorer' &&
Browser.Version() == 6) {
if(!e){var e = window.event;}
var obj = e.srcElement;
tempX = event.clientX + (document.documentElement.scrollLeft
|| document.body.scrollLeft);
tempY = event.clientY + (document.documentElement.scrollTop
|| document.body.scrollTop);
var tooltip = document.getElementById('ie6SelectTooltip');
tooltip.innerHTML = obj.options.title; tooltip.style.left = tempX;
tooltip.style.top = tempY+10;
tooltip.style.width = '100%';
tooltip.style.display = 'block';
}
}
function hideIE6Tooltip(e){
if (navigator.appName=='Microsoft Internet Explorer' &&
Browser.Version() == 6) {
var tooltip = document.getElementById('ie6SelectTooltip');
tooltip.innerHTML = '';
tooltip.style.display = 'none';
}
}
function getCheckBoxListItemsChecked(elementId) {
var elementRef = document.getElementById(elementId);
var checkBoxArray = elementRef.getElementsByTagName('input');
var checkedValues = '';
var checkedText = '';
var checkedSelIndex = '';
var myCheckBox = new Array();
for (var i = 0; i < checkBoxArray.length; i++) {
var checkBoxRef = checkBoxArray[i];
if (checkBoxRef.checked == true) {
if (checkedSelIndex.length > 0)
checkedSelIndex += ', ';
checkedSelIndex +=i;
if (checkedValues.length > 0)
checkedValues += ', ';
checkedValues += checkBoxRef.value;
var labelArray = checkBoxRef.parentNode.getElementsByTagName('label');
if (labelArray.length > 0) {
if (checkedText.length > 0)
checkedText += ', ';
checkedText += labelArray[0].innerHTML;
}
}
}
myCheckBox[0] = checkedText;
myCheckBox[1] = checkedValues;
myCheckBox[2] = checkedSelIndex;
return myCheckBox;
}
function readCheckBoxList(chkBox, ddlList, hiddenFieldText,
hiddenFieldValue, hiddenFieldSelIndex) {
var checkedItems = getCheckBoxListItemsChecked(chkBox);
$get(ddlList).options[0].innerHTML = checkedItems[1]; $get(ddlList).title = checkedItems[0]; $get(hiddenFieldValue).value = checkedItems[1];
$get(hiddenFieldText).value = checkedItems[0];
$get(hiddenFieldSelIndex).value = checkedItems[2];
}
MultipleSelection.ascx
In this page, I have a HoverMenuExtender, DropDownList, CheckBoxListExCtrl, a few hidden fields, and a div to display tooltip information for IE 6.0. And, I have added some dummy data to my checkboxlist so it wouldn't look empty when I drag it onto the page.
<div>
<cc2:HoverMenuExtender ID="HoverMenuExtender1"
runat="server"
TargetControlID="MultiSelectDDL"
PopupControlID="PanelPopUp"
PopupPosition="bottom"
OffsetX="6"
PopDelay="25" HoverCssClass="popupHover">
</cc2:HoverMenuExtender>
<asp:DropDownList ID="MultiSelectDDL"
CssClass="ddlMenu regularText"
runat="server">
<asp:ListItem Value="all">Select
</asp:DropDownList>
<asp:Panel ID="PanelPopUp"
CssClass="popupMenu" runat="server">
<cc1:CheckBoxListExCtrl ID="CheckBoxListExCtrl1"
CssClass="regularText" runat="server">
<asp:ListItem Value="d1">Dummy 1
<asp:ListItem Value="d2">Dummy 2
<asp:ListItem Value="d3">Dummy 3
<asp:ListItem Value="d4">Dummy 4
<asp:ListItem Value="d5">Dummy 5
<asp:ListItem Value="d6">Dummy 6
<asp:ListItem Value="d7">Dummy 7
<asp:ListItem Value="d8">Dummy 8
</cc1:CheckBoxListExCtrl>
</asp:Panel>
<asp:HiddenField ID="hf_checkBoxValue" runat="server" />
<asp:HiddenField ID="hf_checkBoxText" runat="server" />
<asp:HiddenField ID="hf_checkBoxSelIndex" runat="server" />
</div>
<div id="ie6SelectTooltip"
style="display:none;position:absolute;padding:1px;border:1px
solid #333333;;background-color:#fffedf;font-size:smaller;z-index: 99;">
</div>
MS_With_UserControl_and_Masterpage.aspx
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:Label ID="Label1" CssClass="regularText"
runat="server" Text="Month:" />
<uc1:MultipleSelection ID="MultipleSelection1" runat="server" />
MS_With_UserControl_and_Masterpage.aspx.cs - How to bind the data
DataTable dt = new DataTable();
DataColumn dcValue = new DataColumn("Value", typeof(string));
DataColumn dcText = new DataColumn("Text", typeof(string));
dt.Columns.Add(dcText);
dt.Columns.Add(dcValue);
DataRow dr;
dr = dt.NewRow();
dr["Text"] = "January";
dr["Value"] = "m1";
dt.Rows.Add(dr);
…
MultipleSelection1.CreateCheckBox(dt, "Text", "Value");
How to set the selected value
MultipleSelection1.selectedIndex = "1,5,7";
How to get the SelectedIndex, SelectedValue, SelectedText
MultipleSelection1.sText
MultipleSelection1.sValue
MultipleSelection1.selectedIndex
Points of interest
For some reason, I didn't load the ScriptManager dynamically. So, make sure you include a ScriptManager on the page before using the user control, or you will come across this error message: "The control with ID 'HoverMenuExtender1' requires a ScriptManager on the page. The ScriptManager must appear before any controls that needs it."
"Invalid postback or callback argument. Event validation is enabled using…". Initially, I was trying to modify the value of the dropdownlist through JavaScript, and I kept getting the error whenever I hit the Submit button. The easiest solution was to set EnableEventValidation = false on the page directive, but instead, I found another workaround by using a hidden field.
The tooltip (title) was displaying correctly in IE 7.0, 8.0, Firefox, and Google Chrome, but not in IE 6.0. In order to remedy the problem, I included a separate function to show and hide the tooltip.
I am using a checkboxlist control and having difficulty to get the checkboxlist value and text using JavaScript. After conducting some research, I came across a class library by Trilochan Nayak. I have modified his class so that I can retrieve the value and text of the selected checkbox through the JavaScript.
References