Introduction
This is a simple date-picker control that comes as an ASP.NET custom control. The user can either enter a date into a textbox or click on an icon which opens a pop-up calendar. JavaScript is used to display the pop-up calendar. The control can easily be integrated in your own ASP.NET websites by simply referencing the Assembly and drag'n'drop the control from the toolbox onto your web form.
Background
This control is originally based on another CodeProject article. In my first release back in 2007, I overworked the control so it compiles with VS2005 and works with the latest versions of Firefox and Internet Explorer. I fixed some JavaScript errors and added better design time support and data-binding. In the first release, the date-picker control was a so called User Control (.ascx file) which you had to include in your ASP.NET web project, together with some JavaScript, CSS and image files.
Now, in 2011, I publish a new major release. This time, the date-picker is implemented as a Custom Control. This means that it comes as an Assembly (DLL file) which you can simply reference from your ASP.NET web application and then drag'n'drop from the toolbox onto your web form. All required resources like JavaScript, CSS or images files are included in the single DLL and loaded as web resources.
Using the Code
To use the date picker control in your own web project, simply add a reference to the DatePickerControl.dll which you can download from the link at the top of this page.
To manually add a datepicker instance to an .aspx form, add the following code:
<%@ Register assembly="DatePickerControl"
namespace="DatePickerControl" tagprefix="cc1" %>
<cc1:DatePicker ID="DatePicker1" runat="server" />
If you want to have the datepicker
control into your toolbox, you need to manually add it. To do so, right click into the toolbox and select "Choose items..." from the context menu. Then click on the "Browse..." button and select the DatePickerControl.dll. A new control will appear in your toolbox which you can drag'n'drop to any web form:
What I Have Learned
During the development of this custom control, I learnt a lot of things about custom control development. There are a few points of interest I like to share.
Web Resources
My control is using additional resources like images, CSS and JavaScript files. Because I wanted everything to be included into a single DLL, I added all the required files as "embedded resources". Make sure that the "Build Action" in the properties for all the resource files is set to "Embedded Resource". Then you need to edit the "AssemblyInfo.cs" file and add a "WebResource
" declaration for each file that you want to access via an auto-generated URL:
[assembly: System.Web.UI.WebResource("DatePickerControl.Resources.popcalendar.css",
"text/css")]
[assembly: System.Web.UI.WebResource("DatePickerControl.Resources.popcalendar.js",
"text/javascript", PerformSubstitution = true)]
[assembly: System.Web.UI.WebResource("DatePickerControl.Resources.calendar.gif",
"image/gif")]
To get the URL to one of the resource files, use the "Page.ClientScript.GetWebResourceUrl
" method. For example, to include the JavaScript file, I use the following code:
Page.ClientScript.RegisterClientScriptInclude(this.GetType(), "js",
Page.ClientScript.GetWebResourceUrl(this.GetType(),
"DatePickerControl.Resources.popcalendar.js"));
It is very important to add the assembly name to the string
passed to the "Page.ClientScript.GetWebResourceUrl
" method!
BTW: The URL returned by the "Page.ClientScript.GetWebResourceUrl
" method looks something like this:
/WebResource.axd?d=VKJPowiRQrngH4t6...wQza83c1&t=634583660937215237
Property Default Values
I also wanted some design time support, for example properties of my control should have a default value. And I wanted the default value to appear as default (=not bold) in the property grid, whereas non-default values should appear as non-default (=bold):
In case of String
, Int
or Enum
properties, this is pretty easy and can be achieved by adding some extra attributes to the property declaration:
[Category("Appearance")]
[Description("Day to start week with.")]
[Browsable(true)]
[DefaultValue(Weekday.Monday)]
public Weekday StartWeekWithDay
{
But for the DateFormat
property, I wanted the default to be culture dependent: On a European Windows installation, the default date format should be dd.MM.yyyy, whereas on U.S. system, the default should be MM/dd/yyyy. How could this be done? Fortunately, we can also write our own code to set the default value of a property. To do so, we have to add two private
methods for the property. These methods must be named Reset...()
and ShouldSerialize...()
, where the ...
is replaced with the name of the property. Let's look at the DateFormat
property:
public string DateFormat
{
get { return dateFormat; }
set { dateFormat = value; }
}
private void ResetDateFormat()
{
DateFormat = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
}
private bool ShouldSerializeDateFormat()
{
return (!DateFormat.Equals
(CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern));
}
The ResetDateFormat()
method just sets the property to whatever should be your default value. The ShouldSerializeDateFormat()
method returns a boolean that is used to determine whether the property value needs to be serialized. This is only the case if it is different from its default value.
HTML Design Time
In the designer, the date picker control is displayed quite different than on a real web page. Unfortunately, I could not figure out a way to display the calendar image from the embedded resources during design-time:
However, I learned that you can control the HTML that is used to render a control during design-time by adding a class inherited from "ControlDesigner
" to your control DLL. The class must be named the same as the control but with a "Designer
" suffix. For the "DatePicker
" control, this class would be named "DatePickerDesigner
". Within this class, the "GetDesignTimeHtml()
" method can be overridden to return a custom HTML string
.
CSS and JavaScript Include
If you place the date picker control onto a web form, it should automatically include the required CSS and JavaScript files. However if you place two or more date picker controls on the same page, these files should only be included once. To include a JavaScript file, the "RegisterClientScriptInclude
" method can be used:
Page.ClientScript.RegisterClientScriptInclude
(this.GetType(), "js", "your_javascript.js");
This method automatically ensures that the same JavaScript is only included once, even if the method is called multiple times from multiple control instances.
Including a CSS file is a bit more complicated. As we all know, CSS files should be included within the <head></head>
tags of your web page. The controls within the page header can be accessed via the "Page.Header
" property. A link to a CSS file can be added using the following code:
LiteralControl include = new LiteralControl
("<link href='your_css.css' rel='stylesheet' type='text/css' />");
Page.Header.Controls.Add(include);
But how can we make sure that the same CSS is only included once if multiple date picker controls are added to the same page? We can make use of the "RegisterClientScriptInclude
" method mentioned before. There is another method "Page.ClientScript.IsClientScriptIncludeRegistered
" that we can use to query whether a JavaScript has already been included or not. So we can simply include the CSS only if the JavaScript has not already been included.
History
- December 2007 -- Original version posted
- April 2009 -- Updated (many bugfixes, moved to VS2008, examples added)
- August 2010 -- Updated source code and demo
- December 2011 -- Rewritten as a custom control, everything compiled into one DLL, moved to VS2010, more examples added