So below I'm going to share with you a fairly easy to use and understand ASP.NET User Control that allows you to pick a Date (with the ajaxToolkit CalenderExtender) and also select the Time of day using a drop down list. I've named the control DateAndTimePicker.ascx. Since it does use the AjaxControlToolkit, you will have to add a reference to the AjaxControlToolkit in your application, and also on the ASP.NET web page that has the DateAndTimePicker.ascx control.
I'll break the code up so that you can see the HTML and C# code behind in both the DateAndTimePicker.ascx control, and on the ASP.NET page that the control is placed on. So here goes:
Here is the HTML from the DateAndTimePicker.ascx:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="DateAndTimePicker.ascx.cs" Inherits="admin_Controls_DateAndTimePicker" %>
<div>
<table>
<tr>
<td valign="top" style="padding-top:8px;">Date: </td>
<td valign="top">
<asp:TextBox ID="PostDateTextBox" runat="server" Width="100px"></asp:TextBox> <span style="font-size:10px">Date Format: <asp:Literal ID="DateFormatLiteral" runat="server"></asp:Literal></span>
<ajaxToolkit:CalendarExtender ID="CalendarExtender1" runat="server" TargetControlID="PostDateTextBox">
</ajaxToolkit:CalendarExtender><br />
<asp:RequiredFieldValidator ID="DateRequiredFieldValidator1" runat="server" ControlToValidate="PostDateTextBox"
ErrorMessage="Date is Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="DateCompareValidator1" runat="server" ControlToValidate="PostDateTextBox" ErrorMessage="Date must be formated as a date"
Operator="DataTypeCheck" Type="Date"></asp:CompareValidator><br />
</td>
<td valign="top" style="padding-top:8px;">Time: </td>
<td valign="top">
<div id="TimePickeDiv" style="width:350px;display:inline-table;">
<asp:TextBox ID="TimeOfDayTextBox" runat="server" Width="90px" /><asp:Image ID="DropDownImage" runat="server" ImageUrl="~/admin/images/dropdownbtn.gif" ImageAlign="AbsMiddle" /> <span style="font-size:10px">Time format: <asp:Literal ID="TimeFormatLiteral" runat="server"></asp:Literal></span>
<div style="position:relative;">
<asp:ListBox ID="TimeHourHalfListBox" runat="server" Rows="8" style="width:120px;position:absolute;left:0px;display:none;"></asp:ListBox>
<asp:RequiredFieldValidator ID="TimeRequiredFieldValidator1" runat="server" ControlToValidate="TimeOfDayTextBox"
ErrorMessage="Time is Required"></asp:RequiredFieldValidator>
<asp:CustomValidator ID="TimeFormatCustomValidator" runat="server" ErrorMessage="Time format is invalid" OnServerValidate="TimeFormatCustomValidator_ServerValidate"></asp:CustomValidator>
</div>
</div>
</td>
</tr>
</table>
</div>
Here is the C# Code Behind of the DateAndTimePicker.ascx.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text;
public partial class admin_Controls_DateAndTimePicker : System.Web.UI.UserControl
{
private DateTime _currentDateTimeUtc;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
DateFormatLiteral.Text = System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern;
TimeFormatLiteral.Text = System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortTimePattern;
// Populate TimeHour ListBox
PopulateTimes();
//writer.AddAttribute("onClick", "__timepicker_showpopup('" + listid + "')");
DropDownImage.Attributes.Add("onClick", "__timepicker_showpopup('" + TimeHourHalfListBox.ClientID + "')");
TimeHourHalfListBox.Attributes.Add("onfocusout", "__popup_losefocus(this);");
TimeHourHalfListBox.Attributes.Add("onchange", "__timepicker_timechanged('" + TimeOfDayTextBox.ClientID + "',this);");
}
}
public System.DateTime SelectedDateTime
{
get
{
return SelectedDate.Add(SelectedTime.TimeOfDay);
}
set
{
SelectedDate = value;
SelectedTime = value;
}
}
private System.DateTime SelectedDate
{
get
{
//EnsureChildControls();
DateTime d = DateTime.UtcNow;
try
{
d = DateTime.Parse(PostDateTextBox.Text.Trim());
_currentDateTimeUtc = d;
}
catch
{
//Post Date must be formated as a date
DateCompareValidator1.IsValid = false;
return d;
}
return d;
}
set
{
//EnsureChildControls();
PostDateTextBox.Text = value.ToShortDateString();
}
}
private System.DateTime SelectedTime
{
get
{
//EnsureChildControls();
System.DateTime d = DateTime.UtcNow;
try
{
d = System.DateTime.Parse(TimeOfDayTextBox.Text);
}
catch
{
// Time must be formated as a time
TimeFormatCustomValidator.IsValid = false;
return d;
}
return d;
}
set
{
//EnsureChildControls();
string s = value.ToString("h:mm tt");
// Set the TextBox
TimeOfDayTextBox.Text = s;
ListItem item = TimeHourHalfListBox.Items.FindByText(s);
if (item != null)
{
TimeHourHalfListBox.SelectedValue = s;
}
}
}
private void PopulateTimes()
{
if (TimeHourHalfListBox.Items.Count == 0)
{
TimeHourHalfListBox.Items.Add("12:00 AM");
TimeHourHalfListBox.Items.Add("12:30 AM");
for (int i = 1; i <= 11; i++)
{
TimeHourHalfListBox.Items.Add(i + ":00 AM");
TimeHourHalfListBox.Items.Add(i + ":30 AM");
}
TimeHourHalfListBox.Items.Add("12:00 PM");
TimeHourHalfListBox.Items.Add("12:30 PM");
for (int i = 1; i <= 11; i++)
{
TimeHourHalfListBox.Items.Add(i + ":00 PM");
TimeHourHalfListBox.Items.Add(i + ":30 PM");
}
}
}
protected void TimeFormatCustomValidator_ServerValidate(object source, ServerValidateEventArgs args)
{
System.DateTime d = DateTime.UtcNow;
try
{
DateTime dateTime;
if(System.DateTime.TryParse(TimeOfDayTextBox.Text, out dateTime) == false)
{
args.IsValid = false;
}
}
catch
{
// Time must be formated as a time
//TimeFormatCustomValidator.IsValid = false;
args.IsValid = false;
}
}
protected void Page_PreRender(object sender, EventArgs e)
{
commonScript.WritePopupRoutines(Page);
StringBuilder sb = new StringBuilder();
sb.AppendLine("function __timepicker_showpopup(name)");
sb.AppendLine("{");
sb.AppendLine(" if (__popup_panel != null)");
sb.AppendLine(" {");
sb.AppendLine(" document.getElementById(__popup_panel).style.display='none';");
sb.AppendLine(" }");
sb.AppendLine(" __popup_panel=name;");
sb.AppendLine(" var panel=document.getElementById(__popup_panel);");
sb.AppendLine(" panel.style.display='block';");
sb.AppendLine(" panel.focus();");
sb.AppendLine(" window.event.cancelBubble=true;");
sb.AppendLine("}");
sb.AppendLine("function __timepicker_timechanged(tbxid, selectid)");
sb.AppendLine("{");
sb.AppendLine("document.getElementById(tbxid).value=selectid.options[selectid.selectedIndex].text;");
sb.AppendLine(" if (__popup_panel != null)");
sb.AppendLine(" {");
sb.AppendLine(" document.getElementById(__popup_panel).style.display='none';");
sb.AppendLine(" __popup_panel=null;");
sb.AppendLine(" }");
sb.AppendLine("}");
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "popup", sb.ToString(), true);
}
public static class commonScript
{
public static void WritePopupRoutines(System.Web.UI.Page Page)
{
StringBuilder sb = new StringBuilder();
sb = new StringBuilder();
sb.AppendLine("var __popup_panel;");
sb.AppendLine("function __popup_clear() {");
sb.AppendLine(" if (__popup_panel != null ) ");
sb.AppendLine(" {");
sb.AppendLine(" document.getElementById(__popup_panel).style.display='none';");
sb.AppendLine(" __popup_panel=null;");
sb.AppendLine(" }");
sb.AppendLine("}");
sb.AppendLine("function __popup_losefocus(panel)");
sb.AppendLine("{");
sb.AppendLine(" if (!panel.contains(document.activeElement))");
sb.AppendLine(" {");
sb.AppendLine(" panel.style.display='none';");
sb.AppendLine(" }");
sb.AppendLine("}");
Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "PopupRoutines", sb.ToString(), true);
}
}
}
Here's the HTML on my testing page for an ASP.NET page named TestDateTimePicker.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestDateTimePicker.aspx.cs" Inherits="test_datetime_TestDateTimePicker" %>
<%@ Register src="~/admin/Controls/DateAndTimePicker.ascx" tagname="DateAndTimePicker" tagprefix="uc1" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Test Date And Time Picker User Control</title>
</head>
<body style="padding:100px;">
<form id="form1" runat="server">
<asp:ScriptManager id="ScriptManager2" runat="Server" EnableScriptGlobalization="true"></asp:ScriptManager>
<div>
<uc1:DateAndTimePicker ID="DateAndTimePickerNew1" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
<br /><br />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</div>
</form>
</body>
</html>
Here is the C# code behind from my testing page for an ASP.NET page named TestDateTimePicker.aspx:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class test_datetime_TestDateTimePicker : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
DateAndTimePickerNew1.SelectedDateTime = DateTime.UtcNow;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
Label1.Text = DateAndTimePickerNew1.SelectedDateTime.ToString();
}
}
}
That's it... A couple things to note:
- I'm using UTC DateTime, so if your application /database is not coded to run using UTC dates, then I would change "DateTime.UtcNow" to "DateTime.Now"
- Some of the code was derived from an older DateAndTimePicker.ascx control that was in one of the old ASP.NET Starter Kits. However, I didn't like the way it's calendar was built, and the fact that it would cause my pages to Page.MaintainScrollPositionOnPostBack = true; on PreRender even when the calender pop-up control wasn't clicked. This was anonying because I did not want my pages to Maintain Scroll Back Position. So using the AjaxToolkit calender extender is a much more fluid and easy process.
- You may need to make this control more flexible to handle ValidationGroups, currently I don't use the DateAndTimePicker.ascx control on pages where I need to assign any Validators to a ValidationGroup, but it could easily be added in to make it a little more functional.
Hopefully, this DateAndTimePicker.ascx control comes in handy for you!