Introduction
From time to time, I have needed to have a listbox that depends on another listbox. And not only one for each form, but as many as I needed for each form. This article explains how to accomplish this.
Using the code
This code uses MagicAjax to handle the data without having to post the whole page. The function AddDependentListBox()
creates a MagicAjax AjaxPanel in RunTime. DropDownList adds it to the AjaxPanel and then adds the AjaxPanel to the page. In this example a PlaceHolder is used, but a Table or any another control will also suffice.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using MagicAjax;
namespace RuntimeDependentListBox
{
public class DependentListBox : System.Web.UI.Page
{
protected System.Web.UI.WebControls.PlaceHolder ph;
private void Page_Load(object sender, System.EventArgs e)
{
AddDependentListBox("Example_Key");
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}
<summary /> <summary /> <summary /> <summary /></summary />private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
NOTE: When creating the first DropDownList, an EventHandler for the SelectedIndexChange is also created. This provides the DataBinding of the second DropDownList according to the value selected in the first. As a UniqueKey is provided in the AddDependentListBox()
function, this lets the EventHandler know by the IDs which DropDownList to populate. This, in turn, lets the user add as many RunTime-dependent ListBoxes as he or she wants.
private void AddDependentListBox(string pstrKey)
{
MagicAjax.UI.Controls.AjaxPanel ap =
new MagicAjax.UI.Controls.AjaxPanel();
DropDownList cboFirst = new DropDownList();
cboFirst.ID = "1_" + pstrKey;
cboFirst.AutoPostBack = true;
cboFirst.SelectedIndexChanged += new EventHandler(
cboFirst_SelectedIndexChanged);
DropDownList cboSecond = new DropDownList();
cboSecond.ID = "2_" + pstrKey;
cboSecond.Enabled = false;
ap.Controls.Add(cboFirst);
ap.Controls.Add(cboSecond);
ph.Controls.Add(ap);
PopulateFirst(pstrKey);
}
private void PopulateFirst(string pstrKey)
{
DropDownList cboFirst = (DropDownList)Page.FindControl(
"1_" + pstrKey);
cboFirst.Items.Clear();
cboFirst.Items.Add(new ListItem("Select",""));
cboFirst.Items.Add(new ListItem("First Value","1"));
cboFirst.Items.Add(new ListItem("Second Value","2"));
}
private void cboFirst_SelectedIndexChanged(object sender,
System.EventArgs e)
{
DropDownList cboFirst = (DropDownList)sender;
string strKey = cboFirst.ID.Split('_')[1].ToString();
DropDownList cboSecond = (DropDownList)Page.FindControl(
"2_" + strKey);
if(cboFirst.SelectedIndex>0)
{
PopulateSecond(strKey, cboFirst.SelectedValue.ToString());
cboSecond.Enabled = true;
}
else
{
cboSecond.Items.Clear();
cboSecond.Enabled = false;
}
}
private void PopulateSecond(string pstrKey, string pstrcboFirstValue)
{
DropDownList cboSecond = (DropDownList)Page.FindControl(
"2_" + pstrKey);
cboSecond.Items.Clear();
if(pstrcboFirstValue=="1")
{
cboSecond.Items.Add(new ListItem(
"First Value Selected 1","1"));
cboSecond.Items.Add(new ListItem(
"First Value Selected 2","2"));
cboSecond.Items.Add(new ListItem(
"First Value Selected 3","3"));
}
else if(pstrcboFirstValue=="2")
{
cboSecond.Items.Add(new ListItem(
"Second Value Selected 1","1"));
cboSecond.Items.Add(new ListItem(
"Second Value Selected 2","2"));
}
}
}
}
The creation of the MagicAjax AjaxPanel in Runtime for each group of dependent ListBoxes is what allows Ajax to load only the ListBoxes that are inside their AjaxPanel, without interfering in the others.
Conclusion
Well, that's it actually. Although the code is very simple, many developers feel strange about using controls created on the fly. However, this articles uses simple code to improve dependent ListBoxes using C# and Ajax.
History