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 finding in one web user control. This web user control consists of an ASP.NET AJAX HoverMenuExtender, JavaScript, StyleSheet and CheckBoxListExCtrl. The final product will work with or without a masterpage and you can drag and drop more than one instances of the control on to the page. This is not a perfect control, feel free to modify it to tailor your requirement 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 ASP.NET AJAX HoverMenuExtender and create multiple selection dropdownlist.
Before we begin, here is the structure of my project.
The project includes:
CheckBoxListExCtrl
The popup panel with a CheckBoxList control will appear whenever the user moves the mouse over the DropDownList. In order to capture the CheckBoxList selected value and text without any complication; I utilized the CheckBoxListExCtrl class by Trilochan Nayak. This class inherits the CheckBoxList property and allows us to access its selected value and text through the JavaScript. 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.
//09042009 BT - var 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("/>"); //09042009 BT - close the input tag writer.Write("<label for="" + clientID + "">"); //09042009 BT - added label to hold the checkbox text writer.Write(Items[repeatIndex].Text); //text writer.Write("</label>"); //close label tag
MultipleSelectionDDLCSS.css - style sheet
MultipleSelectionDDLJS.js Here is the content of the JavaScript, please read the comments. The tooltip (title) is 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 call showIE6Tooltip to show and hide the tooltip. The function getCheckBoxListItemsChecked will return the selected value, text and index of the CheckBoxList in an array. The readCheckBoxList function will takes the CheckBoxListExCtrl, DropDownList and all the hidden fields ClientID as parameters and set the hidden fields value.
/*detect the browser version and name*/ var Browser = { Version: function() { var version = 999; // we assume a sane browser if (navigator.appVersion.indexOf("MSIE") != -1) // bah, IE again, lets downgrade version number version = parseFloat(navigator.appVersion.split("MSIE")[1]); return version; } } function showIE6Tooltip(e){ //we only want this to execute if ie6 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; //set the title to the div //display the tooltip based on the mouse location tooltip.style.left = tempX; tooltip.style.top = tempY+10; tooltip.style.width = '100%'; tooltip.style.display = 'block'; } } function hideIE6Tooltip(e){ //we only want this to execute if ie6 if (navigator.appName=='Microsoft Internet Explorer' && Browser.Version() == 6) { var tooltip = document.getElementById('ie6SelectTooltip'); tooltip.innerHTML = ''; tooltip.style.display = 'none'; } } /* get and set the selected checkbox value and text and selected index to a hidden field */ function getCheckBoxListItemsChecked(elementId) { //var 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) { //selected index if (checkedSelIndex.length > 0) checkedSelIndex += ', '; checkedSelIndex +=i; //value if (checkedValues.length > 0) checkedValues += ', '; checkedValues += checkBoxRef.value; //text 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]; //set the dropdownlist value $get(ddlList).title = checkedItems[0]; //set the title for the dropdownlist //set hiddenfield value $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 controls, and a div to display tooltip information for IE 6.0. 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> <asp:ListItem Value="d2">Dummy 2</asp:ListItem> <asp:ListItem Value="d3">Dummy 3</asp:ListItem> <asp:ListItem Value="d4">Dummy 4</asp:ListItem> <asp:ListItem Value="d5">Dummy 5</asp:ListItem> <asp:ListItem Value="d6">Dummy 6</asp:ListItem> <asp:ListItem Value="d7">Dummy 7</asp:ListItem> <asp:ListItem Value="d8">Dummy 8</asp:ListItem> </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" />
Code behind - MultipleSelection.ascx.cs Here is the code behind for the user control. In the Page_Load method, I added a client script onclick event to the CheckBoxListExCtrl control. The JavaScript function readCheckBoxList will assign the selected value, text and index to the hidden fields. I also added the onmousemove and onmouseout events for the DropDownList control which will show the tolltip for IE6.0. The LoadJScript() and the LoadCSS() method will load the JavaScript and style sheet dynamically with no duplicates. If you drag and drop multiple instances of the control onto the page, it will only register the StyleSheet and JavaScript one time only. Notice that I utilized the ResolveUrl() method so that the usercontrol will never have problem locating the style sheet and JavaScript.
protected void Page_Load(object sender, EventArgs e) { LoadJScript(); LoadCss(); //add attributes CheckBoxListExCtrl1.Attributes.Add("onclick", "readCheckBoxList('" + CheckBoxListExCtrl1.ClientID + "','" + MultiSelectDDL.ClientID + "','" + hf_checkBoxText.ClientID + "','" + hf_checkBoxValue.ClientID + "','" + hf_checkBoxSelIndex.ClientID + "');"); MultiSelectDDL.Attributes.Add("onmousemove", "showIE6Tooltip();"); MultiSelectDDL.Attributes.Add("onmouseout", "hideIE6Tooltip();"); if (!string.IsNullOrEmpty(hf_checkBoxValue.Value)) { SetDropDownListText(hf_checkBoxValue.Value); } if (!string.IsNullOrEmpty(hf_checkBoxText.Value)) { SetToolTip(hf_checkBoxText.Value); } } //selected checkbox value public string sValue { get { return hf_checkBoxValue.Value; } } //selected checkbox text public string sText { get { return hf_checkBoxText.Value; } } //selected checkbox text public string selectedIndex { get { return hf_checkBoxSelIndex.Value; } set { SetCheckBoxList(value); } } //load style css internal void LoadCss() { //prevent loading multiple css style sheet HtmlControl css = null; if (Session["MultipleSelectionDDLCSSID"] != null) { css = Page.Header.FindControl(Session["MultipleSelectionDDLCSSID"] as string) as HtmlControl; } if (css == null) { //load the style sheet HtmlLink cssLink = new HtmlLink(); cssLink.ID = "MultipleSelectionDDLCSSID"; cssLink.Href = ResolveUrl("~/MS_Control/MultipleSelectionDDLCSS.css"); cssLink.Attributes.Add("rel", "stylesheet"); cssLink.Attributes.Add("type", "text/css"); // Add the HtmlLink to the Head section of the page. Page.Header.Controls.Add(cssLink); Session["MultipleSelectionDDLCSSID"] = cssLink.ID; } } //load the javascript internal void LoadJScript() { ClientScriptManager script = Page.ClientScript; //prevent duplicate script if (!script.IsStartupScriptRegistered(this.GetType(), "MultipleSelectionDDLJS")) { script.RegisterStartupScript(this.GetType(), "MultipleSelectionDDLJS", ""); } } //bind the checkboxlist public void CreateCheckBox(DataTable dt, string dataTextField, string dataValueField) { CheckBoxListExCtrl1.DataSource = dt; CheckBoxListExCtrl1.DataTextField = dataTextField; // "Text"; CheckBoxListExCtrl1.DataValueField = dataValueField;// "Value"; CheckBoxListExCtrl1.DataBind(); SetDropDownListText("Select"); } internal void SetDropDownListText(string txt) { MultiSelectDDL.Items.Clear(); MultiSelectDDL.Items.Add(new ListItem(txt)); } internal void SetToolTip(string title) { MultiSelectDDL.Attributes.Add("title", title); } //check the checkboxlist public void SetCheckBoxList(string index) { string[] strArray; strArray = index.Split(@",".ToCharArray()); string chkBoxIndex = string.Empty; string chkBoxValue = string.Empty; string chkBoxText = string.Empty; if (strArray.Length > 0) { int result; foreach (string s in strArray) { result = 0; if (int.TryParse(s, out result)) { CheckBoxListExCtrl1.Items[result].Selected = true; //index if (chkBoxIndex.Length > 0) chkBoxIndex += ", "; chkBoxIndex += result.ToString(); //value if (chkBoxValue.Length > 0) chkBoxValue += ", "; chkBoxValue += CheckBoxListExCtrl1.Items[result].Value; //text if (chkBoxText.Length > 0) chkBoxText += ", "; chkBoxText += CheckBoxListExCtrl1.Items[result].Text; } } SetDropDownListText(chkBoxText); SetToolTip(chkBoxText); hf_checkBoxSelIndex.Value = chkBoxIndex; hf_checkBoxText.Value = chkBoxText; hf_checkBoxValue.Value = chkBoxValue; } }
This is a usercontrol, just drag and drop. But make sure to include the ScriptManager.
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); … //datasource, dataTextField, dataValueField MultipleSelection1.CreateCheckBox(dt, "Text", "Value");
How to set selected value
MultipleSelection1.selectedIndex = "1,5,7";
How to get the SelectedIndex, SelectedValue, SelectedText
MultipleSelection1.sText MultipleSelection1.sValue MultipleSelection1.selectedIndex
For some reason I didn't load the ScriptManager dynamically. So, make sure you include a ScriptManager on the page before using the usercontrol 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 need it."
"Invalid postback or callback argument. Event validation is enabled using…". Initially, I was trying to modify the value of the dropdownlist through the JavaScript and I kept getting the error whenever I hit the submit button. The easiest solution was to set the EnableEventValidation = false on the page directive, but instead, I found another work around by using hidden field.
The tooltip (title) were displaying correctly on IE 7.0, 8.0, FireFox and Google Chrome but not in IE6.0. In order to remedy the problem, I included a separate function to show and hide the tooltip.
I am using a checkboxlist controls 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.
How do you get the value from a CheckBoxList using JavaScript How to get the CheckBoxlist Value using Javascript? Easiest way to check IE version with JavaScript How to display tooltip for Select control in HTML? Injecting Client-Side Script from an ASP.NET Server Control How Do I: Use the ASP.NET AJAX HoverMenu Extender?
Demo
Download
What kind of email newsletter would you prefer to receive from CodeAsp.Net?18