Introduction
The article provides an example of how to develop an ASP.NET Date Picker server control, utilising: embedded web resources, client scripts, inner properties, and globalization (date formatting). It includes both source and ready to use build/demo.
Background
I've been hunting around for a free open source date picker control for a little while, and couldn't find one that quite met my needs. Since I have not had the chance to make my own server control before, I thought I would create a date picker control and share my experience.
This release had two main focuses. Firstly, due to being Australian (d/MM/yyyy) I wanted the control to be compatible with different culture date formats through the use of globalization. Secondly, the control needed to provide a high level style/appearance control by utilizing the inner property persistence mode.
Using the Code
The DatePicker
server control is an input control that lets the user select a date from a calendar. By default, the Culture
property of the control is set to CultureInfo.CurrentCulture
, which uses the current culture of the web application/server. However, the DatePicker
control can also use a different culture by changing the value of the Culture
property to a new CultureInfo
. The selected date text displayed in the DatePicker
control is displayed in the format specified by using the Culture
property.
The DatePicker
control contains several properties that allow you to control the appearance of the control. Styles can be applied to different elements of the calendar pane using either markup or code behind. The display width of the DatePicker
control, in Units, is determined by its Width
property. Due to an issue encountered with Internet Explorer, the width of the control is set by the width of the textbox.
You can also specify the first day of the calendar week by changing the value of the FirstDayOfWeek
property. By default, the first day of week is set to Sunday. The date that represents today's date can also be changed by setting the value of the TodaysDate
property. Similarly, you can set the DateSelected
property.
The DatePicker
control allows for auto postback when the date selected is changed. This can be set by changing the value of the AutoPostBack
property.
DatePicker Members
Public Properties
AlternateMonthStyle
: Gets or sets style of day cells for next and pervious month.AutoPostBack
: Gets or sets whether the control will postback on selected date changed. Default value is False
.CalendarTableStyle
: Gets or sets style of inner calendar table.PaneWidth
: Gets or sets width of floating pane. Default is 150px.Culture
: Gets or sets culture of control. Default is CultureInfo.CurrentCulture
.DayHeaderStyle
: Gets or sets style of calendar day header row.FirstDayOfWeek
: Gets or sets the calendar's first day of week.MonthStyle
: Gets or sets the day cell style of the current month position.NextPrevMonthStyle
: Gets or sets the style of the next/previous month navigation link.NextPrevYearStyle
: Gets or sets the style of the next/previous year navigation link.PaneHeaderStyle
: Gets or sets the style of the pane header.PaneTableStyle
: Gets or sets the style of the pane. Can be used to change the border style of pane.SelectedDate
: Gets or sets the selected date of the control.SelectedStyle
: Gets or sets the style of the selected date day cell.TitleStyle
: Gets or sets the style of the month calendar title.TodaysDate
: Gets or sets the date that represent today's date.TodayStyle
: Gets or sets the style of today's day cell.
Public Events
SelectedDateChanged
: Occurs when selected date is successfully changed. If the date cannot be parsed, an error will be thrown.
Points of Interest
Embedding Web Resources
To access embedded resources like images and JavaScript that are stored within your server control assembly, you can utilise the WebResource attribute. After either creating a resources file or changing the build action of a file (to "embedded resource"), you can insert WebResource
assembly references into the namespace of your class.
[assembly: WebResource("SlimeeLibrary.Images.DatePicker.gif","image/gif")]
[assembly: WebResource("SlimeeLibrary.Javascript.DatePicker.js", "text/javascript")]
[assembly: WebResource("SlimeeLibrary.Javascript.DateTime.js", "text/javascript")]
namespace SlimeeLibrary
{
}
Registering Client Scripts
In combination with using embedded web resources for the client JavaScript, you can utilise the Page.ClientScript property to check if the control's embedded web resources are already registered and to register any new JavaScript.
The following example checks to see if a script is already registered. If not, it will register the script.
if (!Page.ClientScript.IsClientScriptIncludeRegistered(this.GetType(), "DatePicker"))
{
Page.ClientScript.RegisterClientScriptInclude("DatePicker",
Page.ClientScript.GetWebResourceUrl(this.GetType(),
"SlimeeLibrary.Javascript.DatePicker.js"));
}
Persistence Mode Inner Properties
To allow styles to be defined in ASP.NET markup, you can utilise the PersistenceModeAttribute.Mode attribute property. Defining the persistence mode of your class property will enable this functionality.
[Category("Appearance"),
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerProperty),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public TableStyle PaneTableStyle
{
get
{
if (_paneTableStyle == null)
{
_paneTableStyle = new TableStyle();
_paneTableStyle.BorderStyle = BorderStyle.Solid;
_paneTableStyle.BorderColor = System.Drawing.ColorTranslator.FromHtml("gray");
_paneTableStyle.BorderWidth = new Unit("1px");
}
return _paneTableStyle;
}
set { PaneTableStyle.CopyFrom(value); }
}
The following ASP.NET markup demonstrates the inner property functionality.
<cc1:DatePicker ID="DatePicker1" runat="server" AutoPostBack="true"
Width="100px" PaneWidth="150px">
<PaneTableStyle BorderColor="#707070" BorderWidth="1px" BorderStyle="Solid" />
<PaneHeaderStyle BackColor="#0099FF" />
<TitleStyle ForeColor="White" Font-Bold="true" />
<NextPrevMonthStyle ForeColor="White" Font-Bold="true" />
<NextPrevYearStyle ForeColor="#E0E0E0" Font-Bold="true" />
<DayHeaderStyle BackColor="#E8E8E8" />
<TodayStyle BackColor="#FFFFCC" ForeColor="#000000"
Font-Underline="false" BorderColor="#FFCC99"/>
<AlternateMonthStyle BackColor="#F0F0F0"
ForeColor="#707070" Font-Underline="false"/>
<MonthStyle BackColor="" ForeColor="#000000" Font-Underline="false"/>
</cc1:DatePicker>
Globalization - Controlling Date Formats
By referencing the System.Globalization
namespace and utilizing the CultureInfo.DateTimeFormat property, you can determine the required date format and parse the selected date according to the set culture.
[Category("Behaviour"),
Description("Set the culture for parsing the date values.")]
public CultureInfo Culture
{
get
{
object o = ViewState["Culture"];
return (o != null) ? (CultureInfo)o : CultureInfo.CurrentCulture;
}
set { ViewState["Culture"] = value; }
}
protected virtual void OnSelectedDateChanged(object sender, EventArgs e)
{
if (textBox.Text != string.Empty)
{
try
{
this.SelectedDate = DateTime.Parse(textBox.Text, Culture);
if (SelectedDateChanged != null)
{
SelectedDateChanged(this, e);
}
}
catch (FormatException ex)
{
throw new FormatException("Invalid selected date format.
Could not parse date.", ex);
}
catch (Exception ex)
{
throw new Exception("Unknown exception.", ex);
}
}
}
History
As updates are made to the control, I'll use this area for version control. If you have any ideas or suggestions, don't hesitate to keep me posted. Keep watch of my blog, I'm looking to create more controls soon. I'm also looking for some online projects to contribute to. If you have a project that needs a hand, let me know. Many thanks.
v1.0.2 - Minor Update
2009 October 13: Fixed issue with SelectedDate
property on load
v1.0.1 - Minor Update
2009 October 12: Fixed issue with control rendered IDs when within content place holders