Introduction
This article is about to create a chained dropdownlist when we need to represent data from hierarchical data sets. Here I’ll be discussing the method to populate ASPX dropdown lists using partial page rendering with AJAX. My database is a simple XML data file.
Background
This article is a response to an enquiry raised at another article from me, ‘Creating chained dropdown list using jQuery and XML’ [1]. The enquirer wanted to know security concerns in use of jQuery while programming for a chained dropdown list.
I say, ‘Yes the security concerns are there, those are always when we work at client-side, and we cannot eliminate them at the same point’. While using jQuery method, I found it unable to protect my XML Data file (which is in a separate folder) with the use of Web.config file that can deny all the users to enter that folder.
So if your data is not critical, this slash of security for the sake of performance is not a bad idea, but when the data is critical in nature, better to work with server-side programming. In this article, I’m using ASPX dropdown lists and my XML Data file resides in a protected folder. I’ll be using AJAX so that I could improve the performance by attaining partial page rendering, moreover to this I’m showing a partial update progress bar for the relief of user that something is happening.
Now, the question is which one to opt for - XML Data Files or SQL Server Database. The answer to this question, which come in my mind is, ‘when we have small and static data sets, it is better to use XML data files because it eradicates an unnecessary round trip to the database server of website. But in case of large and dynamically changing data sets, we need to add power in data retrieval through indexing and that is available in any core database language like SQL Server. So in the latter case, it is better to use SQL Server rather than XML.’
Using the Code
Here in the demonstration program, I’m using a .dll file Microsoft.Web.Preview.dll. This has to be added in the Bin folder of the program to attain the feature of partial page update progress panel. Next is the XML file (Motors.xml) which resides in a folder ‘XMLFiles’ with a Web.config file later protests the access to Motors.xml.
On Default.aspx page, there are three dropdown lists, one button
, an UpdateProgress
control (for which we added .dll file) and a Label
to show results. All these are included in UpdatePanel
control with setting the property ChildrenAsTriggers=”true”
. That means any event fired from any of the included control triggers Asynchronous postback to the server. The show/hide of UpdateProgress
control is managed by jQuery code given below:
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
function InitializeRequest(sender,args)
{
$get('chainUpdate').style.display = 'block';
}
function EndRequest(sender,args)
{
$get('chainUpdate').style.display = 'none';
}
In the above code, chainUpdate
is the ID of UpdateProgress
control and there are two functions, the first is being called at the initialization of asynchronous postback and the next is when the call ends.
Now, I’ll discuss about the code at code-behind page. On page load event, I’m loading my XML file in dataset and adding it to Cache to improve performance. Next event call is at Level-Zero dropdownlist (drpMain
), when the selected index gets changed. The handler function is given below:
protected void drpMain_SelectedIndexChanged(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(1200);
if (drpMain.SelectedValue == "0")
{
drpMoto.Items.Clear();
drpBrand.Items.Clear();
drpMoto.Enabled = false;
drpBrand.Enabled = false;
btnGo.Enabled = false;
}
else if (drpMain.SelectedValue == "1")
{
drpMoto.DataTextField = "mcname";
drpMoto.DataValueField = "mcid";
drpMoto.DataSource = ds.Tables["motoc"];
drpMoto.DataBind();
drpMoto.Enabled = true;
drpBrand.Items.Clear();
drpBrand.Enabled = false;
btnGo.Enabled = false;
}
else if (drpMain.SelectedValue == "2")
{
drpMoto.DataTextField = "mbname";
drpMoto.DataValueField = "mbid";
drpMoto.DataSource = ds.Tables["motob"];
drpMoto.DataBind();
drpMoto.Enabled = true;
drpBrand.Items.Clear();
drpBrand.Enabled = false;
btnGo.Enabled = false;
}
}
The first line in the above handler is used to pause the thread for 1200 milliseconds, this is the minimum amount of time to which the UpdateProgress
control will get shown. You can change it as per your requirement.
Now there is a check for selectedvalue
whether it's of default item (zero). It the default item has been selected, item in dropdown lists at Level1
(drpMoto
) and Level2
(drpBrand
) is cleared with disabling both these dropdown lists and the Go button.
In the second condition, when the selectedvalue
is 1
, that is selection is second item in dropdown list drpMain
(cars
in my case) the data relevant to cars has been extracted from dataset and bound to dropdown list at Level1
(drpMoto
) with changing property values of DataTextField
and DataValueField
. Now the list drpMoto
get enabled.
In the third condition, when the selected value is 2 (bikes
in my case), data relevant to bikes has been extracted and bound to dropdown list at Level1
(drpMoto
) with enabling that list.
You will see in all selection changes, the whole page does not post back to the server, there is partial postback with giving a relief by UpdateProgress
control.
Now the time is to discuss event handler written for when there is a change in selection at Level1
dropdown list (drpMoto
), given below:
protected void drpMoto_SelectedIndexChanged(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(1200);
if (drpMoto.SelectedItem.Value == "0")
{
drpBrand.Items.Clear();
drpBrand.Enabled = false;
btnGo.Enabled = false;
}
else if (drpMain.SelectedValue == "1" && drpMoto.SelectedItem.Value != "0")
{
DataView dView = new DataView(ds.Tables["motocb"]);
dView.RowFilter = "mcid='" + drpMoto.SelectedValue.Trim() + "'";
dView.Sort = "mcbname asc";
drpBrand.DataTextField = "mcbname";
drpBrand.DataValueField = "mcbid";
drpBrand.DataSource = dView;
drpBrand.DataBind();
drpBrand.Enabled = true;
btnGo.Enabled = true;
}
else if (drpMain.SelectedValue == "2" && drpMoto.SelectedItem.Value != "0")
{
DataView dView = new DataView(ds.Tables["motobb"]);
dView.RowFilter = "mbid='" + drpMoto.SelectedValue.Trim() + "'";
dView.Sort = "mbbname asc";
drpBrand.DataTextField = "mbbname";
drpBrand.DataValueField = "mbbid";
drpBrand.DataSource = dView;
drpBrand.DataBind();
drpBrand.Enabled = true;
btnGo.Enabled = true;
}
}
In the above handler, there are two condition checks at prime. First is when the selectedvalue
is zero in dropdown list drpMoto
and another is when the selectedvalue
is non-zero in dropdown list drpMoto
. Further, there are two cases when the selected value is non-zero in dropdown list drpMoto
, if the selectedvalue
is 1
in dropdown list drpMain
(for Cars
) or it is 2
(for Bikes
).
At the very first condition when selectedvalue
is 0
in drpMoto
, the items in drpBrand
have been cleared and both drpBrand
and btnGo
go disabled.
In the second condition, we need to extract all brand
nodes for cars and filter them for selection in drpMoto
. Then the dropdown list at Level2
(drpBrand
) goes bound and the drpBrand
and btnGo
gets enabled.
In the third condition, we need to extract all brand
nodes for bikes and filter them for selection in drpMoto
. Then the dropdown list at Level2
(drpBrand
) goes bound and the drpBrand
and btnGo
get enabled.
Now all drop downlists go filled and enabled with button. Final handler function on code-behind page is fired when the button is clicked, given below:
protected void btnGo_OnClick(object sender, EventArgs e)
{
lblResult.Text = "Searched for: " +
drpBrand.SelectedItem.Text.Replace("(","").Replace(")","") + " " +
drpMoto.SelectedItem.Text + " " +
drpMain.SelectedItem.Text.Replace("s","") + "(s)";
}
The above handler is used to simply show the results in a label field.
Points of Interest
Practical stuff is attached as demo. You will easily understand when you look at the downloaded attachment. Here, you might be interested to know about filling dropdown lists using jQuery at client-side, explore my article Creating a chained dropdownlist using jQuery and XML.
Final Words
I hope you find the stuff helpful. Thanks for reading. Good luck!