Custom country-state controls
Introduction
When you develop a Web Application form, very often there is a need to create a combination of Country/State controls.Usually it starts with a country drop down list.
After selecting a particular country, it displays the drop down list of states for countries such as USA and/or Canada, or it displays a text box for free text for other countries.
Some applications do not require the state for countries that do not have a list of states and thus, it should be a flag to display (or not) the textbox.
This trivial situation requires some coding for every page, where you want to place these 2 controls.
Of course it can be done in many different ways: on the client side using JavaScript, using AJAX, JQuery, etc…
For my applications I wanted something really light and convenient, which eliminates a lot of coding, easy to implement, and allows asp.net native validations.
From the very beginning I decided to reload the page when the country has been changed, rather then process the states using JavaScript.
This approach has pros and cons.
A major con is that you have to reload a page, making an extra trip to the server.
For a really busy page it might be a problem because you have to keep all the data already inserted into the page controls.
But this is what the ViewState is for, is it not?
On the positive side this approach does not require any JavaScript code.
-
So I wrote the list of requirements:
- There should be two controls: one for the countries and one for the states (state).
- States control should have the ability to assign the corresponding countries control.
- Each control must be able to work independently from each other.
- Each control must have the default settings (Country and State).
- Each control must have the ability to be validated by the native validation controls.
- The states control should be displayed either as a drop down list or a text box if the country does not have a predefined list of states.
- The states control must have the flag which indicates if to display the text box, in the situation when the country does not have any states.
<world>
<countries>
<country>
<name>AFGHANISTAN</name>
<code>AFG</code>
<states />
<country>
<name>ALBANIA</name>
<code>ALB</code>
<states />
</country>
..............................................
<country>
<name>CAMEROON</name>
<code>CAM</code>
<states />
</country>
<country>
<name>CANADA</name>
<code>CAN</code>
<states>
<state>
<name>ALBERTA</name>
<code>AB</code>
</state>
<state>
<name>BRIT. COLUMBIA</name>
<code>BC</code>
</state>
<state>
<name>MANITOBA</name>
<code>MB</code>
</state>
<state>
<name>N.W. TERRITORY</name>
<code>NT</code>
</state>
<state>
<name>NEW BRUNSWICK</name>
<code>NB</code>
</state>
<state>
<name>NEWFOUNDLAND</name>
<code>NF</code>
</state>
<state>
<name>NOVA SCOTIA</name>
<code>NS</code>
</state>
<state>
<name>ONTARIO</name>
<code>ON</code>
</state>
<state>
<name>PR. EDWARD IS.</name>
<code>PE</code>
</state>
<state>
<name>QUEBEC</name>
<code>PQ</code>
</state>
<state>
<name>SASKATCHEWAN</name>
<code>SK</code>
</state>
<state>
<name>YUKON TERR.</name>
<code>YK</code>
</state>
</states>
</country>
<country>
<name>CAPE VERDE</name>
<code>CAP</code>
<states />
</country>
..............................................
</countries>
</world>
As you see the structure is very simple, but it allows you easily maintain the list up to date.At my application I compiled this file as a Web Resource.
Usually I place all my custom controls into a single class library which I can include into any web project.
Using any document (image, CSS file, JavaScript file, xml file, etc…) as a Web Resource allows you to place it into the compiled format and not care about moving it from application to application.
Use the following link to read more about the Web Resources:
As I wrote before I want to create the ability to assign the countries control to the states control via the states control ID.
This means that in my application I should be able to find the control by its ID.
You know that the FindControl() function looks only through the list of controls of a particular level.
I would rather have the ability to look for a control by ID through all the levels.
That is why I found a very useful blog on the Internet.
I reused the code written by Steve Smith.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
namespace ControlLibrary
{
public static class ControlFinder
{
/// <summary>
/// Similar to Control.FindControl, but recurses through child controls.
/// </summary>
public static T FindControl<T>(Control startingControl, string id) where T : Control
{
T found = startingControl.FindControl(id) as T;
if (found == null)
{
found = FindChildControl<T>(startingControl, id);
}
return found;
}
/// <summary>
/// Similar to Control.FindControl, but recurses through child controls.
/// Assumes that startingControl is NOT the control you are searching for.
/// </summary>
public static T FindChildControl<T>(Control startingControl, string id) where T : Control
{
T found = null;
foreach (Control activeControl in startingControl.Controls)
{
found = activeControl as T;
if (found == null || (string.Compare(id, found.ID, true) != 0))
{
found = FindChildControl<T>(activeControl, id);
}
if (found != null)
{
break;
}
}
return found;
}
}
}
All has been prepared for the controls and we can start
Countries Control
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;
namespace ControlLibrary
{
public class CountryListControl : System.Web.UI.WebControls.DropDownList
{
public string DefaultCountry { get; set; }
protected override void OnLoad(EventArgs e)
{
if (!this.Page.IsPostBack)
{
string URLString = this.Page.ClientScript.GetWebResourceUrl(typeof(CountryListControl), "LOLv2.Resources.TheWorld.xml");
URLString = this.Page.Request.Url.Scheme + "://" + this.Page.Request.Url.Authority + URLString;
XmlDocument doc = new XmlDocument();
doc.Load(URLString);
this.DataTextField = "InnerText";
this.DataSource = doc.SelectNodes("world/countries/country/name");
this.DataBind();
if (!string.IsNullOrEmpty(DefaultCountry))
this.SelectedValue = DefaultCountry;
base.OnPreRender(e);
}
}
}
}
The control inherits from DropDownList.The control defines the DefaultCountry property.
OnLoad event:
When the page is being loaded for the first time, the xml document is being created from the Web Resource.
The DataSource is set to the XmlNodeList with countries names and is bounded to the list.
If the DefaultCountry is assigned, it is set as the selected value.
The States Control
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Web;
using System.Xml;
using System.Web.UI.WebControls;
using System.Web.UI;
using LOLv2;
namespace ControlLibrary
{
public class StateListControl : DropDownList
{
public string CountryControl { get; set; }
public string Country { get; set; }
public bool DisplayEmptyTextBox { get; set; }
public string DefaultState;
private TextBox textBox;
private DropDownList countryDll;
private bool hasStates;
protected override void OnLoad(EventArgs e)
{
this.Visible = true;
}
protected override void OnPreRender(EventArgs e)
{
if (!string.IsNullOrEmpty(CountryControl))
{
countryDll = ControlFinder.FindControl<DropDownList>(this.Page, CountryControl);
}
if (null != countryDll)
Country = countryDll.SelectedItem.Value;
else
Country = string.IsNullOrEmpty(Country) ? "UNITED STATES" : Country;
string URLString = this.Page.ClientScript.GetWebResourceUrl(typeof(StateListControl), "LOLv2.Resources.TheWorld.xml");
URLString = this.Page.Request.Url.Scheme + "://" + this.Page.Request.Url.Authority + URLString;
XmlDocument doc = new XmlDocument();
doc.Load(URLString);
XmlNodeList stateNames = doc.SelectNodes("world/countries/country[name=\"" + Country + "\"]/states/state/name");
XmlNodeList stateCodes = doc.SelectNodes("world/countries/country[name=\"" + Country + "\"]/states/state/code");
if (stateNames.Count == 0)
{
textBox = new TextBox();
hasStates = false;
}
else
{
hasStates = true;
this.Items.Clear();
for (int i = 0; i < stateNames.Count; i++)
{
ListItem li = new ListItem();
li.Text = stateNames[i].InnerText;
li.Value = stateCodes[i].InnerText;
this.Items.Add(li);
}
if (!string.IsNullOrEmpty(DefaultState))
this.SelectedValue = DefaultState;
else
if (null != this.Page.Request[this.ClientID])
try
{
this.SelectedValue = this.Page.Request[this.ClientID];
}
catch { }
}
base.OnPreRender(e);
}
protected override void Render(HtmlTextWriter writer)
{
if (null != textBox)
{
CopyProperties(this, textBox);
textBox.AutoPostBack = this.AutoPostBack;
textBox.CausesValidation = this.CausesValidation;
textBox.RenderControl(writer);
}
else
if (hasStates)
base.Render(writer);
}
private void CopyProperties(WebControl from, WebControl to)
{
to.ID = from.ID;
to.CssClass = from.CssClass;
ICollection keys = from.Attributes.Keys;
foreach (string key in keys)
{
to.Attributes.Add(key, from.Attributes[key]);
}
to.BackColor = from.BackColor;
to.BorderColor = from.BorderColor;
to.BorderStyle = from.BorderStyle;
to.BorderWidth = from.BorderWidth;
to.ForeColor = from.ForeColor;
to.Height = from.Height;
ICollection styles = from.Style.Keys;
foreach (string key in keys)
{
to.Style.Add(key, from.Style[key]);
}
to.ToolTip = from.ToolTip;
to.Visible = from.Visible;
to.Width = from.Width;
}
}
}
As you see the states control is more complicated.The control inherits from the DropDownList.
It has the following properties:
- The public string CountryControl, which is an assigned country Control ID.
- The public string Country, which is the country name
- The public Boolean DisplayEmptyText, which commands to display or not to display the text box - when the country does not have states.
- The public string DefaultState, which defines which state to set as a default.
- The private TextBox object textbox, which will be used for rendering a text box, rather than a drop down list, when the country does not have the state.
- The private DropDownList contryDll, which is used as a place holder for the found countries control
- The private bool hasStates, which is just a flag.
On pageLoad event I set the visibility of the control to True.
This is done in order not to loose the control on the PostBack, if a control is not being displayed before the PostBack.
On Prerender event:
- Look for the countries control
- Define the Country for this control
- Get the data from the Web Resource
- Populate either the existing drop down list, or create a new text box object
Using Render procedure:
If a list of states exists, then render the drop down list, or else render the text box.
As you noticed, I used the CopyProperties procedure to copy any possible property from the original control into the text box (if the text box is rendered).
The result
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="CountryStateList.Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ Register Assembly="ControlLibrary" Namespace="ControlLibrary" TagPrefix="cl1" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<cl1:CountryListControl ID="ddlCountry" runat="server" DefaultCountry="CANADA" AutoPostBack="true">
</cl1:CountryListControl>
<br />
<cl1:StateListControl ID="ddlState" runat="server" CountryControl="ddlCountry" CssClass="ffff"
AutoPostBack="true" DisplayEmptyTextBox="true">
</cl1:StateListControl>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="ddlState"
ErrorMessage="*"></asp:RequiredFieldValidator>
<br />
<asp:Button ID="btnClick" runat="server" Text="Click" />
</div>
</form>
</body>
</html>
This is an example of the Default.aspx page.
You have to register the assembly:
<%@ Register Assembly="ControlLibrary" Namespace="ControlLibrary" TagPrefix="cl1" %>
I placed the RequiredFieldValidator to show that it works with the control.
You can see now how convenient and simple this method is to handle the tedious task of displaying the country/state functionality on your web page. You can download the source.
If you like the article, please vote.
发表评论
XV7lRF Unfortunately, fanminds did not present at the GSummit, so their slides are not included. I\ ad love to hear more about their projects. Please get in touch! Jeff at gamification dot co
LBAtqA Very informative blog. Want more.
qual è il modo migliore per iniziare una società di produzione per adulti ?
Mi puoi raccontare i minori nelle carceri per adulti e prigioni , le leggi statali che li riguardano , statistiques ?
entrare in contatto con un vero e proprio buon sito web per adulti , controllare il web per tutti i negozi online , e poi contattarli e chiedere il possiblity di ottenere i vostri prodotti e stock fuori di loro , saranno molto utili sono sicuro . inoltre, per la collezione di video , lo stesso con l'altro , ottiene un negozio online , e contattarli , cercare di imbastire un affare se si acquista in blocco , sono sicuro che vi darà un buon sconto ... Inoltre , youll bisogno di un piccolo negozio a vendere da naturalmente, e si dovrebbe ottenere un buon design segno , qualcosa che centro dell'attenzione degli occhi , ma non è a buon mercato , contattare un lavoratore in acciaio , e si potrebbe avere a fare un logo o segno per voi , che sarebbe guardare alla moda e più attraente , luci al neon in finestre sono anche usati frequentemente ... si dovrebbe anche fare pubblicità su una rivista o un giornale locale , magari un po ' a buon mercato celeb mag. inoltre , fanno volantini a portata di mano fuori intorno al luogo , . . questo è il massimo che posso fare per voi, spero che aiuta ! . . buona fortuna !
Io certamente no ! Penso che sia una vergogna ! . . Vorrei che sia stato per gli adulti . E ' vergognoso ... . Sono triste vedere che il sito conoscendo la Pasqua è a pochi giorni di distanza e celebro questa festa perché Gesù è morto per noi è ONORE sapere che è morto per noi. Un giorno risusciterà, proprio come ha fatto , è per questo che celebriamo questa festa . . . Mi auguro che il creatore di quel sito aveva intenzioni migliori di come si percepisce . . . Io non sono una persona molto religiosa , ma io conosco la verità della mia fede . . Dio benedica tutti voi avete una felice vacanza .. Dio abbia pietà l'anima della persona che ha progettato quel sito .
Is there a degree that exists for use of music AND creative writing two fields? If there is, do you know the name of it?. . I want to combine these two of my interests (loves) but I don't know what kind of degree offers the use of both.. . Please help? Approaching college?.
What is the best absolutely free blog/web or search engine directory on the web?
This is a wonderful post
How long can my computer keep running with an outdated browser?
POR FAVOR, ESCRIBAMOS MILLONES DE CARTAS A LA AGENCIA ESA PIDIENDO QUE PROHIBAN LA VENTA DE “ALCACHOFAS”, YA QUE SON FLORES COMESTIBLES
No tenia ni la menys remota idea de que havien instalat aquesta antena a la torre de la nostra Seu Vella. Quina vergonya! . Supongo que aprovechando las obras de remodelación y aprovechando que tuvieron que reparar con carácter de urgencia alguno de los pináculos de la torre ya que habían sufrido varios desprendimientos, alguna empresa aprovechó para poder negociar instalar dicha antena a cambio de una buena cantidad de dinero. Dinero repartido entre el ayuntamiento de LLeida y la Generalitat. Voy a escribirles una carta a la asociación “amigos de la Seu Vella” para denunciar este hecho y para que nos den explicaciones, ya que son los primeros que están defendiendo la protección de la Seu, su rehabilitación, etc… haciendo actos, excursiones y otras actividades. A ver que explicaciones nos dan. .Hasta pronto.
De toute manière existe-t-il une presse écrite Chrétienne sérieuse en France? A part “Familles Chrétiennes” qui mettait un peu gentiment les pieds dans le plat, les journaux et magazines “Chrétiens” y font pâle figure.
Nizza leggere , ho appena passato questo su un collega che stava facendo qualche ricerca su questo. E che in realtà mi ha comprato il pranzo da quando l'ho trovato per lui sorriso Quindi mi permetta di riformulare che: Grazie per il pranzo! saluti !
Hahah, Il mio portatile è caduto quando stavo visitando questo sito l'ultima volta che sono stato qui. E per ultimi 2 mesi ho cercato questo weblog, così grata l'ho trova ancora una volta! : D
Invidio la tua capacità di pubblicare bellissimo articolo - voleva semplicemente dire che in questo modo!
Grazie per aver reso il tentativo sincero di parlare di questo. Mi sento molto forte al riguardo e vorrei saperne di più. Se va bene, come ottenere la saggezza in più ampia, potrebbe mente compresi articoli aggiuntivi simili a questo con informazioni aggiuntive? Sarà straordinariamente utile e disponibile per me ei miei amici.
Grazie una tonnellata per il vostro tempo e fatica per mettere insieme queste cose su questo blog. Janet e ho anche molto apprezzato i vostri suggerimenti tra i tuoi articoli su certe cose . So che avete una grande varietà di richieste proprio programma da qui il fatto che hai preso tutto il tempo proprio come avete fatto a guidare le persone come noi per mezzo di questo articolo è anche molto apprezzato .
Apprezzo molto questo post. Ho cercato dappertutto per questo! Grazie a Dio ho trovato su Bing . Hai fatto il mio giorno! Grazie ancora ..
Post molto informativo. Grazie per aver condiviso la tua vista con noi.
Credo che gli altri proprietari del sito devono assumere questo sito come un modello, lo stile di utente molto pulita e accogliente e di design eccellente, per non parlare del contenuto. Sei un esperto in questo argomento!
Come un principiante, io sono sempre alla ricerca online per gli articoli che mi può aiutare. Grazie Wow! Grazie! Ho sempre voluto scrivere nel mio sito qualcosa di simile. Posso prendere parte del tuo post sul mio blog?
Total Control Marketing Overview - great piece of detail that you ? Ye received the article on this site . I hope I can get a lot more material on its website . I 'll come again.
Definitely one of the challenges which individuals starting a new on-line firm face is that of acquiring visitors to their net site.
Really like your web sites details! Undoubtedly a wonderful supply of knowledge that is extraordinarily helpful. Stick with it to hold publishing and that i’m gonna proceed studying by the use of! Cheers.
Total Control Marketing Review - grande pezzo di dettagli che hai ricevuto su questo articolo sito. Spero di poter eventualmente ottenere alcuni molto di più delle cose sul vostro sito web. Arriverò di nuovo.
I’ve lately started a weblog, the data you present on this web site has helped me tremendously. Thanks for your whole time & work.