Recently, I was tasked with merging 3 similar screens into one. I took stock of the commonalities and decided a Category
and Subcategory
dropdown list would suffice. As you’d expect, the contents of the Subcategory
dropdown depend on the selected Category
. Obviously, I wanted to avoid postbacks so I first looked to the Ajax Control Toolkit’s CascadingDropDown extender to link the parent to the child. In my case, there were only a dozen subcategories
so a webservice
seemed like overkill.
After attending Tech-Ed 2008 and seeing Microsoft throwing its weight behind jQuery, I decided to have a look. So what follows is my first foray into jQuery and I’m quite pleased with the results.
First, we define an enum
in the codebehind which can be used for bitwise operations.
public enum Category
{
Invoice = 1,
Order = 2,
Shipment = 4
}
Next, I wanted to be able to use the enum
to specify the Category
(only specifying one) and Subcategory
items (bitwise OR any combination).
_DropDownCategory.Items.Add(GenerateListItem("Orders", Category.Order, false));
_DropDownCategory.Items.Add(GenerateListItem("Invoices", Category.Invoice, false));
_DropDownCategory.Items.Add(GenerateListItem("Shipments", Category.Shipment, false));
_DropDownSubcategory.Items.Add(GenerateListItem("Purchase Orders",
Category.Invoice | Category.Order | Category.Shipment, false));
_DropDownSubcategory.Items.Add(GenerateListItem("Quote Number", Category.Order, false));
_DropDownSubcategory.Items.Add(GenerateListItem("Customer Project Number",
Category.Shipment, true));
…
The enum
was converted to a number and added as a custom attribute to the new list item in GenerateListItem()
:
li.Attributes.Add("Category", ((int)eCat).ToString());
Enter jQuery, first we’re going to need to keep a copy of all the available Subcategory
items. Each time we change the Category
, we will be showing a subset of this array which we must keep separate in memory.
var optSubCat = null;
$(function() {
optSubCat = $("#_DropDownSubcategory").children().clone();
ddSubcategoryUpdate(2);
});
Then, we need an event to fire when the Category
is changed.
$(function() {
$("#_DropDownCategory")
.bind("change", function(event) {
var eCat = this[this.selectedIndex].attributes("Category").value;
ddSubcategoryUpdate(eCat);
});
});
Note how jQuery allows us to wire up DOM events after the fact to our .NET controls. Here, we add an onchange
event dynamically rather than injecting this via the codebehind which forces us to put JavaScript code in the wrong place. All we’re doing is pulling the value of the enum
from the selected Category
and then passing it to a function which will update the Subcategory
items.
function ddSubcategoryUpdate(eCat) {
$("#_DropDownSubcategory").children().remove();
$(optSubCat).each(function() {
if (($(this).attr("Category") & eCat) > 0) {
$("#_DropDownSubcategory").append($(this).clone()[0]);
}
});
}
And finally, in the if
statement, we see we test each Subcategory
item previously saved in memory to see if it matches the enum
value of the Category
.
What we’ve ended up with is a very powerful yet simple mechanism for cascading dropdowns using enum
s in our codebehind
. It’s easier to wire up than what the Ajax Control Toolkit provides, it's all script so the UI looks good, and while this could have been done in straight JavaScript, it demonstrates the power and simplicity of the jQuery library.