Recently a project of mine used an ASP.NET calendar control to allow the user to enter their date of birth, but I discovered that a calendar control is good for selecting date from the current, next, or previous month, but obviously the date of birth would need many navigations of months. It is not feasible.

The following will demonstrate how to make the Calendar control more flexible in terms of its navigation through the addition of two drop-down lists.

First create a User Control so that a customized calendar control can be used on any .aspx page.

I have attached a simple project which guides you to the use of a customized calendar control to enter Date Of Birth (DOB).

Customizing Calendar Control

1. First add the Asp.Net Calendar control with some styles applied.

<asp:Calendar ID="calDate" runat="server"
BackColor="White" BorderColor="#3366CC" CellPadding="1" DayNameFormat="Shortest"
Font-Names="Verdana" Font-Size="8pt" ForeColor="#003399" Height="200px"
Width="250px" ondayrender="calDate_DayRender">
<SelectedDayStyle BackColor="#009999" Font-Bold="True" ForeColor="#CCFF99" />
<TodayDayStyle BackColor="#99CCCC" ForeColor="White" />
<SelectorStyle BackColor="#99CCCC" ForeColor="#336666" />
<WeekendDayStyle BackColor="#CCCCFF" />
<OtherMonthDayStyle ForeColor="#999999" />
<NextPrevStyle Font-Size="8pt" ForeColor="#CCCCFF" />
<DayHeaderStyle BackColor="#99CCCC" ForeColor="#336666" Height="1px" />
<TitleStyle BackColor="#003399" BorderColor="#3366CC" BorderWidth="1px" Font-Bold="True"
Font-Size="10pt" ForeColor="#CCCCFF" Height="25px" />
</
asp:Calendar>

2. Dropdown Lists for month and year collection.

For month dropdown hardcode the data in design page only, for year dropdown in code behind bind the data.
Code
<asp:DropDownList ID="Ddyear" runat="server" AutoPostBack="True"
Code
    onselectedindexchanged="DdyearSelectedIndexChanged">
Code
</asp:DropDownList>
Code
<asp:DropDownList ID="Ddmonth" runat="server" AutoPostBack="True"
Code
    onselectedindexchanged="DdmonthSelectedIndexChanged">
Code
     <asp:ListItem Value="00">*Month*</asp:ListItem>
Code
    <asp:ListItem Value="01">Jan</asp:ListItem>
Code
    <asp:ListItem Value="02">Feb</asp:ListItem>
Code
    <asp:ListItem Value="03">March</asp:ListItem>
Code
    <asp:ListItem Value="04">april</asp:ListItem>
Code
    <asp:ListItem Value="05">May</asp:ListItem>
Code
    <asp:ListItem Value="06">June</asp:ListItem>
Code
    <asp:ListItem Value="07">July</asp:ListItem>
Code
    <asp:ListItem Value="08">August</asp:ListItem>
Code
    <asp:ListItem Value="09">Sept</asp:ListItem>
Code
    <asp:ListItem Value="10">Oct</asp:ListItem>
Code
    <asp:ListItem Value="11">Nov</asp:ListItem>
Code
    <asp:ListItem Value="12">Dec</asp:ListItem>
Code
</asp:DropDownList>

3. For year dropdown data is bound on page load:
Code
Code
protected void Page_Load(object sender, EventArgs
e)
Code
{
Code
   if
(IsPostBack) return;
    else
Code
    {
Code
        var al
= new ArrayList();
Code
        al.Add("*Year*");
Code
        for (var i = 1900; i <=2011; i++)
Code
        {
Code
            al.Add(i);
Code
        }
Code
        Ddyear.DataSource = al;
Code
        Ddyear.DataBind();
Code
    }
Code
}
SQL
4. These dropdown lists will be added to the calendar header by overriding the Render method.
The previous month navigation icon (i.e. '<' left side of calendar header) is replaced by a month dropdownlist.

Next the month navigation icon (i.e. '>' right side of calendar header) is replaced by a year dropdownlist.

In the middle of the calendar header the selected month name and year will be displayed (ex: March 1989)
Code
Code
#region Regular expressions
Code
  private static Regex
regPrevMonth = new Regex(
Code
  @"(?<PrevMonth><a.*?><</a>)",
Code
  RegexOptions.IgnoreCase
Code
  | RegexOptions.Singleline
Code
  | RegexOptions.CultureInvariant
Code
  | RegexOptions.IgnorePatternWhitespace
Code
  | RegexOptions.Compiled
Code
  );
Code
  private static Regex
regNextMonth = new Regex(
Code
  @"(?<NextMonth><a.*?>></a>)",
Code
  RegexOptions.IgnoreCase
Code
  | RegexOptions.Singleline
Code
  | RegexOptions.CultureInvariant
Code
  | RegexOptions.IgnorePatternWhitespace
Code
  | RegexOptions.Compiled
Code
  );
Code
  #endregion
Code
  protected override void Render(HtmlTextWriter writer)
Code
  {
Code
      // turn user
control to html code
Code
      string
output = CalControl1.RenderToString(calDate);
Code
      MatchEvaluator
mevm = new MatchEvaluator(AppendMonth);
Code
      output = regPrevMonth.Replace(output,
mevm);
Code
      MatchEvaluator
mevb = new MatchEvaluator(AppendYear);
Code
      output = regNextMonth.Replace(output,
mevb);
Code
      // output the
modified code
Code
      writer.Write(output);
Code
  }
Code
  public static string
RenderToString(Control c)
Code
  {
Code
      bool
previousVisibility = c.Visible;
Code
      c.Visible = true;
// make visible if not
Code
      // get html
code for control
Code
      System.IO.StringWriter
sw = new System.IO.StringWriter();
Code
      HtmlTextWriter
localWriter = new HtmlTextWriter(sw);
Code
      c.RenderControl(localWriter);
Code
      string
output = sw.ToString();
Code
      // restore
visibility
Code
      c.Visible = previousVisibility;
Code
      return
output;
Code
  }
Code
  private string AppendMonth(Match
m)
Code
  {
Code
      return CalControl1.RenderToString(Ddmonth) + "&nbsp" ;
Code
  }
Code
  private string AppendYear(Match
m)
Code
  {
Code
      return  "&nbsp"
+ CalControl1.RenderToString(Ddyear);
Code
  }

5. Initially calendar shows current date, and then it displays whichever date you select.

The code to set current date to show at first time is as below

public DateTime? SelectedDate
{
get
{
// null date stored or not set
if (ViewState["SelectedDate"] == null)
{
return null;
}
return (DateTime)ViewState["SelectedDate"];
}
set
{
ViewState["SelectedDate"] = value;
if (value != null)
{
calDate.SelectedDate = (DateTime)value;
calDate.VisibleDate = (DateTime)value;
}
else
{
calDate.SelectedDate = new DateTime(0);
calDate.VisibleDate = DateTime.Now.Date;
}
}
}
6. Finally we need code for event handlers for Calendar DayRender, DdmonthSelectedIndexChanged and DdyearSelectedIndexChanged as follows.


protected void calDate_DayRender(object sender, DayRenderEventArgs e)
{
HyperLink hlnk = new HyperLink();
hlnk.Text = ((LiteralControl)e.Cell.Controls[0]).Text;
hlnk.Attributes.Add("href", "javascript:SetDate('" +
e.Day.Date.ToString("dd/MM/yyyy") + "')");
e.Cell.Controls.Clear();
e.Cell.Controls.Add(hlnk);
}
protected void DdyearSelectedIndexChanged(object sender, EventArgs e)
{
var syear = DateTime.Now.Year;
var smonth = DateTime.Now.Month;
if (Ddmonth.SelectedValue != "00")
{
smonth = Convert.ToInt32(Ddmonth.SelectedValue);
}
if (Ddyear.SelectedValue!="*Year*")
{
syear = Convert.ToInt32(Ddyear.SelectedValue);
}
var date = smonth + "/" + DateTime.Now.Day + "/" +syear;
var dateTime = Convert.ToDateTime(date);
calDate.VisibleDate = dateTime;
}
protected void DdmonthSelectedIndexChanged(object sender, EventArgs e)
{
var smonth = DateTime.Now.Month;
var year = DateTime.Now.Year;
if (Ddyear.SelectedValue != "*Year*")
{
year = Convert.ToInt32(Ddyear.SelectedValue);
}
if (Ddmonth.SelectedValue != "00")
{
smonth = Convert.ToInt32(Ddmonth.SelectedValue);
}
var sdate = smonth + "/" + DateTime.Now.Day + "/" + year;
calDate.VisibleDate = Convert.ToDateTime(sdate);
}
CSS
The above code completes Customizing calendar control. Now we will look at a simple example of how to use this control to enter a DOB. (The complete source code is available for downloading.)

1) In the first Page (ex calendar.aspx) create a Textbox for the DOB and one image button or anchor tag to open a calendar in popup onclick of it. Pass a TexBox id to the popup to assign a selected date to the TexBox.
Code
Code
<asp:textbox id="tbMyDate" runat="server" Width="80px"></asp:textbox>
HTML / XML
  <a href="" onclick="return PopupPicker('tbMyDate')"><img src="Images/Calendar_scheduleHS.png" alt="Picture" 
border="0"></a>
Code
JavaScript to open popup:
Code
Code
function PopupPicker(ctl) {
Code
        var PopupWindow = null;
Code
        PopupWindow = window.open('PopupCalendar.aspx?Ctl=' + ctl, 'PopupWindow', 'width=10,height=250,resizable=yes');
Code
        PopupWindow.focus();
Code
       return false;
CSS
    };

2) In the "PopupCalendar.aspx" page we need to register a user control that has a customized calendar. And we need to handle the "SetDate()" JavaScript function which calls on selecting a date from a calendar. It assigns the selected date to the DOB TextBox
and closes the popup. See the calDate_DayRender method definition.

<%@ Register src="CalControl1.ascx" tagname="CalControl1" tagprefix="uc2" %>
Code
<uc2:CalControl1 ID="CalControl11" runat="server" />
Code
 function SetDate(dateValue) {
Code
            ctl = window.location.search.substr(1).substring(4);
Code
            thisForm = window.opener.document.forms[0].elements[ctl].value = dateVae;
Code
             self.close();
Code
          }