Click here to Skip to main content
Email Password   helpLost your password?

Introduction

My task was to create a simple DropDownList containing U.S. States and Canadian Provinces that could be reused easily. The requirements were that it should be entirely self-contained and should operate exactly like any other DropDownList.

For this reason, it made the most sense to subclass the DropDownList component, and load the ItemList within the overloaded OnInit event.

Contents

This package contains two controls, SDIddlStates and SDIddlCountries. This article contains code snippets from the SDIddlStates control. However, the SDIddlCountries control is almost identical, as you will see as soon as you look at it. In fact, you could easily combine the two and add a new parameter that the user could set at design-time to establish which type it is. That would be a very good exercise.

Using the code

To use the code, simply compile it. Then, within the Visual .NET IDE, choose the TOOLS | Add/Remove Toolbox Items... menu option and browse until you find the DLL that resulted from the compilation. You should them be able to drag-and-drop the control onto any Web Form you need it.

Points of Interest

Accessing the required Classes

The code requires the use of certain classes, so we must grab their definitions, like this:

using System;
using System.Collections;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;

Subclassing the DropDownList

The next thing we need to do is begin the code by declaring the new class, which I call SDIddlStates, like this:

    public class SDIddlStates : DropDownList 
    {
    ...all of the code will go here...
    }

Overriding the OnInit Event

In order to preload the ItemList, which contains the Values and Text of the DropDownList control, I wrote the following code:

    protected override void OnInit(EventArgs e)
    {
        // Create the DataSource that contains the data

        this.DataSource = CreateDataSource();
        
        // Tell the control what column in the DataSource contains the Text

        this.DataTextField = "StatesTextField";

        // Tell the control what column in the DataSource contains the Value

        this.DataValueField = "StatesValueField";

        // Bind the DataSource to the control

        this.DataBind();

        // Do whatever the control usually does OnInit

        base.OnInit(e);
    }

Creating the DataSource

In order to create the DataSource that is used in the code, above, I wrote the following code:

    protected ICollection CreateDataSource() 
    {

        // Create a table to store data for the DropDownList control.

        DataTable dt = new DataTable();
        
        // The first column of the DataSource contains the Text

        dt.Columns.Add(new DataColumn("StatesTextField", typeof(String)));

        // The second column of the DataSource contains the Value

        dt.Columns.Add(new DataColumn("StatesValueField", typeof(String)));

        // Populate the table with rows.

        dt.Rows.Add(CreateRow("0", "Choose a State/Province", dt));
        dt.Rows.Add(CreateRow("AL", "Alabama", dt));
        dt.Rows.Add(CreateRow("AK", "Alaska", dt));
        ...
        dt.Rows.Add(CreateRow("SK", "Saskatchewan", dt));
        dt.Rows.Add(CreateRow("YT", "Yukon Territories", dt));

        // Create a DataView from the DataTable to act as the 

        // DataSource for the DropDownList control.

        DataView dv = new DataView(dt);
        return dv;
    }

Creating the DataRow

In order to create the DataRow that is used in the code, above, I wrote the following code:

    protected DataRow CreateRow(String Value, String Text, DataTable dt)
    {
        // Create a DataRow using the DataTable defined in the 

        // CreateDataSource method.

        DataRow dr = dt.NewRow();

        // The first column of the DataSource contain the Text

        dr[0] = Text;

        // The second column of the DataSource contain the Value

        dr[1] = Value;

        return dr;
    }

Putting the Control in the Toolbox

To be able to drag-and-drop the control from the Toolbox, I had to make sure I could put it in the toolbox to begin with. So I wrote this code:

    [
    ToolboxData("<{0}:SDIddlStates runat="server">")
    ]

Note that the name of the control in the Toolbox must match the class name.

History

V1.01

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralMissing Alberta AB
Kyle Morris
12:55 9 Aug '07  

Maybe one of the Nunavuts from the above post was meant to be an entry for ALberta?

Thanks for a neat little tool by the way Smile

QuestionStates / Provences DDL
stixoffire
0:52 13 Mar '07  
I noticed you added DataRows and then used that to bind to the DDL, Is there any reason you chose this method and not simply using an Enum.

I am what I call in a learning mode and would like to know if there was a reason or just force of habit ???
Thank you in advance for your answer.
Generali want to retrieve from database
LovelyHelp
2:03 7 Feb '06  
how if i want to retrive the item inside the drop downlist from database? how my code should be?
GeneralWhat type of project
fawaleb
6:57 1 Aug '04  
What type of project do you build this as? ASP.NET Web Application or Web Control Library. As System.Data is not available to the Control Library?
Generalquite useful
amkarkha
14:12 28 May '04  
the control is quite useful.
I think its strength primarily lies in the fact that at one place one can find the list of all states and countries. you would earn a lot of blessings if you make it absolutely positive that there is nothing missing.

GeneralHow to build dll
Scott Kofroth
13:39 27 Jan '04  
Sure would love to use this. I'm fairly new to .net and don't know how to build the dll. Care to help?
Scott Kofroth
skofroth@hotmail.com

GeneralRe: How to build dll
hougie40
6:04 2 Apr '04  
I would also like to see instructions on how to build the dll. What type of project must be created. Obviously a c# project but of what type. Web control, etc. I had errors regarding system.data when I tried to compile.


GeneralRe: How to build dll
atoms
14:40 18 Mar '05  
Did you add the reference for system.data?

I built it as a web control and it seems to work just fine in a web application.
GeneralSystem.Data vs. System.Collection
Gregory Bush
9:04 10 Dec '03  
Hi,
Why are you not using System.Collection instead System.Data.Confused
GeneralDoes this Rebuild list items every time?
chris2121
17:09 10 Nov '03  
i.e. if I was hitting the database for the state list, on page post back
would it have to hit the db again or would the list items be created from the viewstate
GeneralRe: Does this Rebuild list items every time?
jrfinkel
18:27 10 Nov '03  
I beleive the list would have to be regenerated each time the page is generated. THe easiest way to confirm this is to test it and see! I believe all that is saved in the ViewState is the SELECTED text & value, but I may be mistaken.

If you want to have a DropDownList that has values from a database, and you expect to have quite a few post backs, I would suggest you think about retrieving that data once into a static Table, and then assign that as the DataSource of a DropDownList.

You can see how I have built a DataSource and assigned it to the DataSource of the DropDownList. You would do the same thing, except you would load the data from the database into a static table your Page_Load function. You would do this only if PostBack is not True. You would then assign this table as the DropDownList's DataSource.

My SDIddlStates works the way it does because I wanted it to be entirely self-contained, meaning that it would not need any external database or special coding.

I hope this is helpful to you.

Joel Finkel
GeneralRe: Does this Rebuild list items every time?
Tyrone Davis Jr.
7:41 9 Aug '07  
I was able to modify this control to us ControlState to prevent loading every time. See snipped below:

protected override void OnInit( EventArgs e ) {
Page.RegisterRequiresControlState( this );

if ( this.dt == null ) {
// Create the DataSource that contains the data
this.DataSource = CreateDataSource( );

// Tell the control what column in the DataSource contains the Text
this.DataTextField = "StatesTextField";

// Tell the control what column in the DataSource contains the Value
this.DataValueField = "StatesValueField";

// Bind the DataSource to the control
this.DataBind( );
}

// Do whatever the control usually does OnInit
base.OnInit( e );
}

protected override void LoadControlState( object savedState ) {
object[ ] ctrlState = ( object[ ] ) savedState;
base.LoadControlState( ctrlState[0] );
DataTable dt = ctrlState[1] as DataTable;
}

protected override object SaveControlState( ) {
object[ ] ctrlState = new object[ 2 ];
ctrlState[ 0 ] = base.SaveControlState( );
ctrlState[ 1 ] = dt;
return ctrlState;
}

I made the DataTable, which is the datasouce as a private member so I delcared it outside the CreateDataSource method:

DataTable dt = null;

protected ICollection CreateDataSource( ) {

// Create a table to store data for the DropDownList control.
dt = new DataTable( );
......
......

You should be able to get this to work with these minor changes. The dropdown list will maintain its state, no pun intended. So, if you select Alabama, on postback, Alabama will be selected in the list.

Hope this helps.
GeneralNunavut * 2
Warren Stevens
5:57 3 Nov '03  
It looks like there are two entries for Nunavut:

dt.Rows.Add(CreateRow("NU", "Nunavut", dt));
dt.Rows.Add(CreateRow("NU", "Nunavut", dt));

Warren (former Nunavut resident)
GeneralRe: Nunavut * 2
jrfinkel
8:46 5 Nov '03  
Quite right. Nice catch. This would result in a run-time error if a user selected this option, as the control is not graceful if two options are SELECTED. Dead

As you might expect, I scoured the web for drop down lists that contained States and Provinces and simply snarfed the code, which I modified. I did not want to re-type everything! I evidently did not examine it closely enough.

Of course, I did a similar thing for countries, except that I tried to ensure that I used international standard country codes. I add "WB" for West Bank and "GZ" for Gaza. I considered adding "EJ" for East Jerusalem, but decided not to. One could easily do that.

I also placed United States and Cananda at the top of the list. The developer is free to place her/his country at the top for esay access.

Thanks again for the bug report.

-Joel



Last Updated 4 Nov 2003 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010