Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Creating a chained dropdownlist using AJAX and XML

4.44/5 (17 votes)
26 Mar 2010CPOL5 min read 1   681  
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 dropdownlists using partial page rendering with AJAX. My database is a simple XML data file.
prog-snapshot.jpg

exec-snapshot.jpg

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:

C#
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:

C#
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:

C#
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:

C#
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!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)