ASP.NET AjaxToolkit Calendar extender is most used control from AjaxControlToolkit. However developers often give it up, because of some additional business requirements. Usually asp.net developers replace it with standard asp.net calendar control and UpdatePanel. However this is very slow solution, so in this article I'll show you how you can modify AjaxlControlToolkit Calendar Control Extender, so it fits your needs, without touching AjaxControlToolkit source code.
Let's build simple sample of Calendar extender:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<table>
<tr>
<td>
<asp:TextBox ID="txtDate" runat="server" Width="70"></asp:TextBox>
<ajaxToolkit:CalendarExtender ID="ceCalendar" runat="server"
PopupButtonID="ibtnCalendar"
TargetControlID="txtDate">
</ajaxToolkit:CalendarExtender>
</td>
<td>
<asp:ImageButton ID="ibtnCalendar" ImageUrl="~/images/CalendarIcon.jpg" Width="20px" runat="server" />
</td>
</tr>
</table>

Close Button
First of all they always want a close button. At least twice I had to give up for AjaxControlToolkit Calendar, because it doesn't have a close button. What if customer, doesn't want to pick a date, how he can close calendar? I usually reply, that you need to click outside of calendar control. Business guys said that this is not obvious. Calendar need to have close button, like a normal window! Let's give them close button.
To solve this problem we need king of javascript, JQuery (now recongnized even by Microsoft).
<script src="javascript/jquery-1.2.6.min.js" type="text/javascript"></script>
<asp:PlaceHolder runat="server" Visible="false">
<script src="javascript/jquery-1.2.6.min-vsdoc.js" type="text/javascript"></script>
</asp:PlaceHolder>
First line includes jquery itself. Then I have PlaceHolder that doesn't generate any code, since it has Visible equal false. This is a bulletproof way of enabling jquery intellisense.
Let's put little cross in right top corner of calendar. If you inspect ajaxtoolkit calendar with firebug you will see that it consits of div#ceCalendar_container and inside two divs: div#ceCalendar_header and div#ceCalendar_body. So, we need to inject our little cross before those two divs. After we add div with little x, we need to bind handler which will close it onclick.
<script type="text/javascript">
function GenerateCloseButton(sender, e)
{
if ($('#ajax__calendar_close_button').length == 0)
{
$(sender._header).before("<div id='ajax__calendar_close_button'>x</div>");
$('#ajax__calendar_close_button').bind("click", sender, function(e) {
e.data.hide();
});
}
}
</script>
My close button is just a little x, however you can put any fancy image as background of div. Below is some basic css style for close button.
<style type="text/css">
#ajax__calendar_close_button
{
margin-right:5px;
margin-left:auto;
width:10px;
font-weight:bold;
cursor:pointer;
text-align:right;
}
</style>
Last step, you need to bind GenerateCloseButton function to some event in AjaxControlToolkit Calendar. OnClientShown is the best event for this purpose:
<ajaxToolkit:CalendarExtender ID="ceCalendar" runat="server"
PopupButtonID="ibtnCalendar"
TargetControlID="txtDate"
OnClientShown="GenerateCloseButton"
>
</ajaxToolkit:CalendarExtender>

Date restrictions
Second most needed requirement is date restriction
The simplest solution is to check date in OnClientDateSelectionChanged event. However at this point you can't stop calendar from changing selected date and hinding itself. You can try to do some hacks like clear selected date and show calendar again, but this is not we are looking for. Calendar should not hide if I selected wrong date. It should not allow me to select date at all. Let's take a look at Ajaxtoolkit Calendar source code. We are not going to change it. We just take a look at it guts (AjaxControlToolkit source code). Let's open CalendarBehavior.js. It's easy to see that we need to intercept _cell_onclick event. Let's write our own _cell_onclick (we also need to overwrite _button_onblur, so calendar won't hide, when you click ok in alert window).
AjaxControlToolkit.CalendarBehavior.prototype._button_onblur_original = AjaxControlToolkit.CalendarBehavior.prototype._button_onblur;
AjaxControlToolkit.CalendarBehavior.prototype._button_onblur = function(e)
{
if (!this._selectedDateChanging)
{
this._button_onblur_original(e);
}
}
AjaxControlToolkit.CalendarBehavior.prototype._cell_onclick_original = AjaxControlToolkit.CalendarBehavior.prototype._cell_onclick;
AjaxControlToolkit.CalendarBehavior.prototype._cell_onclick = function(e)
{
var target = e.target;
var today_date = new Date();
if (target.date.getFullYear() < 2001)
{
this._selectedDateChanging = true;
alert('Date should be greate than January 1, 2001!');
this._selectedDateChanging = false;
return;
}
if (target.date > today_date)
{
this._selectedDateChanging = true;
alert('You can\'t choose date in future.');
this._selectedDateChanging = false;
return;
}
this._cell_onclick_original(e);
}

Here a final source code of AjaxToolkit Calendar Extender Page
