The HTML List Box is a multi-column select box that mimics the functionality of a list box in a thick client application. The user is able to select and deselect a number of items from what appears to be a select box. In reality, the box is a table within a div which has a set height and an overflow scrollbar. JQuery handles the hovering and selection of the list items. The radio buttons allow the user to select a batch of items within the list. In this case, countries can be selected by continent.
The selected list of items is available through javascript on the client and on the server side with a postback.
See Demo Download Project Files

The HTML
The list of countries is generated by a standard RadioButtonList object.
1: <asp:RadioButtonList ID="rlstCountry" runat="server">
2: <asp:ListItem Text="All" Value="All" />
3: <asp:ListItem Text="Africa" Value="Africa" />
4: <asp:ListItem Text="Antarctica" Value="Antarctica" />
5: <asp:ListItem Text="Asia" Value="Asia" />
6: <asp:ListItem Text="Europe" Value="Europe" />
7: <asp:ListItem Text="N. America" Value="N. America" />
8: <asp:ListItem Text="Oceana" Value="Oceana" />
9: <asp:ListItem Text="S. America" Value="S. America" />
10: <asp:ListItem Text="Custom" Value="Custom" />
11: </asp:RadioButtonList>
The table of countries which form the select box includes a few components. A GridView object is wrapped in a div.
1: <div id="mcsbCountry" class="mcsb">
2: <asp:GridView ID="grvCountry" runat="server"
3: GridLines="None"
4: AutoGenerateColumns="false"
5: ShowHeader="false"
6: ShowFooter="false"
7: OnRowDataBound="grvCountry_RowDataBound">
8: <Columns>
9: <asp:BoundField DataField="Continent" />
10: <asp:BoundField DataField="Name" />
11: </Columns>
12: </asp:GridView>
13: </div>
The stylesheet contains the code that will limit the size of the mcsbCountry div. This will cause the overflow to show the right-side scroll bar. The table generated by the GridView object is styled to make it look like a regular ListBox control.
1: .mcsb
2: {
3: height:>391px;
4: width:>450px;
5: overflow:>auto;
6: cursor:>pointer;
7: font-size:>0.9em;
8: border:>1px solid #DDD;
9: border-right-width:>0px;
10: }
11:
12: .mcsb table
13: {
14: width:>100%;
15: }
16:
17: .mcsb table tr td
18: {
19: white-space:>nowrap;
20: border-bottom:>1px solid #EEE;
21: padding:>0px 0px 0px 4px;
22: }
To maintain the list of selected items, we'll use a HiddenField object. The JQuery will access this control to save a comma-separated list of selected items.
1: <asp:HiddenField ID="hidCountry" runat="server" />
The C#
I've created a Country class that will hold the array of countries that will be bound to the GridView.
1: public class Country
2: {
3: public Country() { }
4:
5: public Country(string continent, string name)
6: {
7: this.Name = name;
8: this.Continent = continent;
9: }
10:
11: private string _Name;
12: public string Name
13: {
14: get { return _Name; }
15: set { _Name = value; }
16: }
17:
18: private string _Continent;
19: public string Continent
20: {
21: get { return _Continent; }
22: set { _Continent = value; }
23: }
24: }
Normally, this object would be delivered through the business object but for this example, I'm going to generate the class manually.
1: protected Country[] GetCountries()
2: {
3: List<Country> countries = new List<Country>();
4: countries.Add(new Country("Africa", "Algeria"));
5: countries.Add(new Country("Africa", "Angola"));
6: countries.Add(new Country("Africa", "Benin"));
7: .
8: .
9: .
10: countries.Add(new Country("S. America", "Venezuela"));
11:
12: return countries.ToArray();
13: }
The array of countries are bound to the GridView.
1: grvCountry.DataSource = GetCountries();
2: grvCountry.DataBind();
In order for the radio list selection to work, we must add attributes to each row. To do this, we'll use the RowDataBound event of the GridView.
1: protected void grvCountry_RowDataBound(object sender, GridViewRowEventArgs e)
2: {
3: Country rec = e.Row.DataItem as Country;
4: if (rec != null)
5: {
6: e.Row.Attributes.Clear();
7: e.Row.Attributes.Add("continent", String.Concat(rec.Continent, " All"));
8: e.Row.Attributes.Add("countryname", rec.Name.Replace("'", "''"));
9: }
10: }
The continent attribute will be used by the JQuery to select which GridView rows relate to which countries. The countryname attribute is the value which will be put into the HiddenField that will tell the client and server which options were selected.
The JQuery
The JQuery will perform the select, deselect and hovering actions of the GridView items.
The hover and click events are added to the each row in the GridView.
1: $('div#mcsbCountry table tr:has(td)').hover(
2: function() { $(this).addClass('hover'); },
3: function() { $(this).removeClass('hover'); }
4: ).click(function() {
5: if ($(this).attr('class').indexOf('selected') > -1) {
6: $('#hidCountry').val($('#hidCountry').val()
.replace($(this).attr('countryname') + ',', ''));
7: $(this).removeClass('selected');
8: }
9: else {
10: $('#hidCountry').val($('#hidCountry').val() + $(this).attr('countryname') + ',');
11: $(this).addClass('selected');
12: }
13: });
The hover event toggles the hover class on the GridView row. The click event is a bit more complicated. The if statement checks to see if the row is already selected. If it is selected, the selected class is removed from the row and the value of the countryname attribute is removed from the HiddenField. If it's not selected, the selected class is applied to the row, and the countryname attribute plus a comma is entered into the HiddenField.
The classes simply change the background color and set the font color to white.
1: .selected td
2: {
3: background : #316AC5;
4: color : #FFF;
5: }
6:
7: .hover td
8: {
9: background : #4198F0;
10: color : #FFF;
11: }
Next, we'll bind the click event to the radio buttons. When a button is clicked, say N. America, the JQuery selector will call the click event of every GridView row that has a continent attribute equal to N. America. Before selecting the ones we want, we deselect the active ones first so we only get the N. American countries.
1: $('input[type=radio][name=rlstCountry]').click(function() {
2: //value of radio button
3: var op = $('input[type=radio][name=rlstCountry]:checked').val();
4:
5: //deselect all
6: $('div#mcsbCountry table tr').removeClass('selected');
7: $('#hidCountry').val('');
8:
9: //select the continent
10: $('div#mcsbCountry table tr[continent*=' + op + ']').click();
11: });
The last step is to interogate the HiddenField in case we are in a postback situtation. We want to re-select all the active items in the GridView. We know the request is a postback if the HiddenField has country names in it. If so, we'll split value with a common and add the selected class to that country in the GridView.
1: if ($('#hidCountry').val().length > 0) {
2: $.each($('#hidCountry').val().split(','), function(i, v) {
3: $('div#mcsbCountry table tr[countryname=' + v + ']').addClass('selected');
4: });
5: }
In the demo, there is additional JQuery code which controls the scrolling of the div. For asthetic reasons, when a continent is selected, the div will scroll to the first instance of that continent so the user receives a visual notification that their items were selected.
See Demo Download Project Files
Compatability

Project Files: HTML_List_Box.zip (76.05 kb)
