In this article I’ll be explaining how to create a simple calendar date selector using three DropDownLists in ASP.Net. The three DropDownLists will correspond to Day, Month and Year.
What’s the need of creating a user control when there are ready made calendars available? The answer is that quite often for end users it seems difficult to use the calendar controls.
So let’s start building our Custom Date Selector Calendar Control
Building the User Control
First we’ll start by creating the HTML Markup and adding the controls to it
Year:<asp:DropDownList ID="ddlYear" runat="server" onchange = "PopulateDays()" />
Month:<asp:DropDownList ID="ddlMonth" runat="server" onchange = "PopulateDays()" />
Day:<asp:DropDownList ID="ddlDay" runat="server" />
<br />
<asp:CustomValidator ID="Validator" runat="server" ErrorMessage="* Required"
ClientValidationFunction = "Validate" />
As you’ll notice above the Markup is very simple. I have added 3 DropDownLists and a Custom Validator that will validate the dates. I am also calling some JavaScript functions which I’ll be describing later.
Then you’ll need to add a new user control to your project and add the following properties to it
C#
private int Day
{
get
{
if (Request.Form[ddlDay.UniqueID] != null)
{
return int.Parse(Request.Form[ddlDay.UniqueID]);
}
else
{
return int.Parse(ddlDay.SelectedItem.Value);
}
}
set
{
this.PopulateDay();
ddlDay.ClearSelection();
ddlDay.Items.FindByValue(value.ToString()).Selected = true;
}
}
private int Month
{
get
{
return int.Parse(ddlMonth.SelectedItem.Value);
}
set
{
this.PopulateMonth();
ddlMonth.ClearSelection();
ddlMonth.Items.FindByValue(value.ToString()).Selected = true;
}
}
private int Year
{
get
{
return int.Parse(ddlYear.SelectedItem.Value);
}
set
{
this.PopulateYear();
ddlYear.ClearSelection();
ddlYear.Items.FindByValue(value.ToString()).Selected = true;
}
}
public DateTime SelectedDate
{
get
{
try
{
return DateTime.Parse(this.Month + "/" + this.Day + "/" + this.Year);
}
catch
{
return DateTime.MinValue;
}
}
set
{
if (!value.Equals(DateTime.MinValue))
{
this.Year = value.Year;
this.Month = value.Month;
this.Day = value.Day;
}
}
}
VB.Net
Private Property Day() As Integer
Get
If (Not (Request.Form(ddlDay.UniqueID)) Is Nothing) Then
Return Integer.Parse(Request.Form(ddlDay.UniqueID))
Else
Return Integer.Parse(ddlDay.SelectedItem.Value)
End If
End Get
Set(ByVal value As Integer)
Me.PopulateDay()
ddlDay.ClearSelection()
ddlDay.Items.FindByValue(value.ToString).Selected = True
End Set
End Property
Private Property Month() As Integer
Get
Return Integer.Parse(ddlMonth.SelectedItem.Value)
End Get
Set(ByVal value As Integer)
Me.PopulateMonth()
ddlMonth.ClearSelection()
ddlMonth.Items.FindByValue(value.ToString).Selected = True
End Set
End Property
Private Property Year() As Integer
Get
Return Integer.Parse(ddlYear.SelectedItem.Value)
End Get
Set(ByVal value As Integer)
Me.PopulateYear()
ddlYear.ClearSelection()
ddlYear.Items.FindByValue(value.ToString).Selected = True
End Set
End Property
Public Property SelectedDate() As DateTime
Get
Try
Return DateTime.Parse(Me.Month & "/" & Me.Day & "/" & Me.Year)
Catch ex As Exception
Return DateTime.MinValue
End Try
End Get
Set(ByVal value As DateTime)
If Not value.Equals(DateTime.MinValue) Then
Me.Year = value.Year
Me.Month = value.Month
Me.Day = value.Day
End If
End Set
End Property
The above properties will be used to get or set the date in our custom date selector.
Next job is to write some code snippet that will populate our three DropDownLists with Days, Month and Year values. The methods below populate the DropDownLists with Day, Month and Year values
C#
private void PopulateDay()
{
ddlDay.Items.Clear();
ListItem lt = new ListItem();
lt.Text = "DD";
lt.Value = "0";
ddlDay.Items.Add(lt);
int days = DateTime.DaysInMonth(this.Year, this.Month);
for (int i = 1; i <= days; i++)
{
lt = new ListItem();
lt.Text = i.ToString();
lt.Value = i.ToString();
ddlDay.Items.Add(lt);
}
ddlDay.Items.FindByValue(DateTime.Now.Day.ToString()).Selected = true;
}
private void PopulateMonth()
{
ddlMonth.Items.Clear();
ListItem lt = new ListItem();
lt.Text = "MM";
lt.Value = "0";
ddlMonth.Items.Add(lt);
for (int i = 1; i <= 12; i++)
{
lt = new ListItem();
lt.Text = Convert.ToDateTime(i.ToString() + "/1/1900").ToString("MMMM");
lt.Value = i.ToString();
ddlMonth.Items.Add(lt);
}
ddlMonth.Items.FindByValue(DateTime.Now.Month.ToString()).Selected = true;
}
private void PopulateYear()
{
ddlYear.Items.Clear();
ListItem lt = new ListItem();
lt.Text = "YYYY";
lt.Value = "0";
ddlYear.Items.Add(lt);
for (int i = DateTime.Now.Year; i >= 1950; i--)
{
lt = new ListItem();
lt.Text = i.ToString();
lt.Value = i.ToString();
ddlYear.Items.Add(lt);
}
ddlYear.Items.FindByValue(DateTime.Now.Year.ToString()).Selected = true;
}
VB.Net
Private Sub PopulateDay()
ddlDay.Items.Clear()
Dim lt As ListItem = New ListItem
lt.Text = "DD"
lt.Value = "0"
ddlDay.Items.Add(lt)
Dim days As Integer = DateTime.DaysInMonth(Me.Year, Me.Month)
Dim i As Integer = 1
Do While (i <= days)
lt = New ListItem
lt.Text = i.ToString
lt.Value = i.ToString
ddlDay.Items.Add(lt)
i = (i + 1)
Loop
ddlDay.Items.FindByValue(DateTime.Now.Day.ToString).Selected = True
End Sub
Private Sub PopulateMonth()
ddlMonth.Items.Clear()
Dim lt As ListItem = New ListItem
lt.Text = "MM"
lt.Value = "0"
ddlMonth.Items.Add(lt)
Dim i As Integer = 1
Do While (i <= 12)
lt = New ListItem
lt.Text = Convert.ToDateTime((i.ToString + "/1/1900")).ToString("MMMM")
lt.Value = i.ToString
ddlMonth.Items.Add(lt)
i = (i + 1)
Loop
ddlMonth.Items.FindByValue(DateTime.Now.Month.ToString).Selected = True
End Sub
Private Sub PopulateYear()
ddlYear.Items.Clear()
Dim lt As ListItem = New ListItem
lt.Text = "YYYY"
lt.Value = "0"
ddlYear.Items.Add(lt)
Dim i As Integer = DateTime.Now.Year
Do While (i >= 1950)
lt = New ListItem
lt.Text = i.ToString
lt.Value = i.ToString
ddlYear.Items.Add(lt)
i = (i - 1)
Loop
ddlYear.Items.FindByValue(DateTime.Now.Year.ToString).Selected = True
End Sub
Note: You will notice that I am populating the day DropDownList after the Month and Year DropDownLists are populated, the reason for this is that I populate the number of days in month based on the values to the selected month and year.
Once these methods are created we can call them in Page Load event in the following way.
C#
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (this.SelectedDate == DateTime.MinValue)
{
this.PopulateYear();
this.PopulateMonth();
this.PopulateDay();
}
}
else
{
if (Request.Form[ddlDay.UniqueID] != null)
{
this.PopulateDay();
ddlDay.ClearSelection();
ddlDay.Items.FindByValue(Request.Form[ddlDay.UniqueID]).Selected = true;
}
}
}
VB.Net
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
If Not IsPostBack Then
If (Me.SelectedDate = DateTime.MinValue) Then
Me.PopulateYear()
Me.PopulateMonth()
Me.PopulateDay()
End If
Else
If (Not (Request.Form(ddlDay.UniqueID)) Is Nothing) Then
Me.PopulateDay()
ddlDay.ClearSelection()
ddlDay.Items.FindByValue(Request.Form(ddlDay.UniqueID)).Selected = True
End If
End If
End Sub
Above when the first time page loads I populate all the three DropDownLists. And when there is PostBack, I have taken care that the selected value of the Day DropDownList is preserved since it is also populated client side and in such cases ViewState doesn’t work.
Client Side Operations
Client Side operations are needed since the day DropDownList is populated based on the values of the Month and Year. Thus in other words based on the values of Month and Year it is decided how many days in a month should be present.
<script type="text/javascript">
function PopulateDays() {
var ddlMonth = document.getElementById("<%=ddlMonth.ClientID%>");
var ddlYear = document.getElementById("<%=ddlYear.ClientID%>");
var ddlDay = document.getElementById("<%=ddlDay.ClientID%>");
var y = ddlYear.options[ddlYear.selectedIndex].value;
var m = ddlMonth.options[ddlMonth.selectedIndex].value != 0;
if (ddlMonth.options[ddlMonth.selectedIndex].value != 0 && ddlYear.options[ddlYear.selectedIndex].value != 0) {
var dayCount = 32 - new Date(ddlYear.options[ddlYear.selectedIndex].value, ddlMonth.options[ddlMonth.selectedIndex].value - 1, 32).getDate();
ddlDay.options.length = 0;
AddOption(ddlDay, "DD", "0");
for (var i = 1; i <= dayCount; i++) {
AddOption(ddlDay, i, i);
}
}
}
function AddOption(ddl, text, value) {
var opt = document.createElement("OPTION");
opt.text = text;
opt.value = value;
ddl.options.add(opt);
}
function Validate(sender, args) {
var ddlMonth = document.getElementById("<%=ddlMonth.ClientID%>");
var ddlYear = document.getElementById("<%=ddlYear.ClientID%>");
var ddlDay = document.getElementById("<%=ddlDay.ClientID%>");
args.IsValid = (ddlDay.selectedIndex != 0 && ddlMonth.selectedIndex != 0 && ddlYear.selectedIndex != 0)
}
</script>
The PopulateDays function as the name suggests populate the day DropDownList client side based on the values of the Month and Year. This avoids the validation checks for leap years. This method gets called when the month and year DropDownList’s values are changed.
The next method AddOption is a generic method that adds values to a DropDownList.
Finally the Validate method validates the three DropDownLists to verify if the user has selected all the values or not. This method is called up by the Custom Validator.
Getting and setting the Date in the Custom Date Selector
Using the SelectedDate property you can easily set and get the Selected Date from the Custom Calendar Date Selector in the following way
C#
//Set Date
ucDateSelector.SelectedDate = DateTime.Parse("05/10/2010");
//Get Date
Response.Write(ucDateSelector.SelectedDate.ToShortDateString());
VB.Net
'Set Date
ucDateSelector.SelectedDate = DateTime.Parse("05/10/2010")
'Get Date
Response.Write(ucDateSelector.SelectedDate.ToShortDateString)
Thus we come to the end of this article. You can download the related source code in VB.Net and C# using the link below
Download Code