Create a Popup Calendar for ASP.NET user controls...

Use the .NET Calendar Control and a little javascript to create a handy popup calendar for your web forms with date text boxes residing in a user control.


By: John Kilgo Date: September 17, 2003 Download the code.

In July, 2003 I wrote an article entitled Create a Popup Calendar for ASP.NET Web Forms. Please refer to that article, using the link above, for a fuller explanation of the technique for creating the popup calendar and populating a textbox with the date selected from the calendar control.

That article has turned out to be one of the most popular articles on DotNetJohn and has been downloaded over a thousand times in a little over two months. After the article was published, however, I received several emails from people pointing out that the technique did not work if the date textboxes were within a user control rather than on the web form itself. I was not able to help them because I couldn't figure out a way to make it work myself. My good friend Ken Walker came to the rescue. I told him about the problem (and he wanted to use the popup calendar in a user control himself) and within an hour or two he came up with the solution.

In this article I will show all of the code and include it all in the download file but I will not spend much time on the techniques except for the technique for making the popup calendar work from within a user control.

First the popup calendar page (PopCal.aspx and its codebehind file) itself. I'll present the code here, but please refer to the previous article for an explanation of how it works if you care for an explanation. First the .aspx page.

<%@ Page Language="vb" AutoEventWireup="false" Codebehind="PopCal.aspx.vb" Inherits="DotNetJohn.PopCal"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>PopCal</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name=vs_defaultClientScript content="JavaScript">
<meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
</head>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<asp:Calendar ID="calDate" OnSelectionChanged="Change_Date" Runat="server" />
<input type="hidden" id="control" runat="server" NAME="control"/>
</form>
</body>
</html>

And now for the codebehind file - PopCal.aspx.vb

Imports System.Web.UI.HtmlControls.HtmlGenericControl

  Public Class PopCal
    Inherits System.Web.UI.Page

    Protected WithEvents control As System.Web.UI.HtmlControls.HtmlInputHidden
    Protected WithEvents calDate As System.Web.UI.WebControls.Calendar

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      control.Value = Request.QueryString("textbox").ToString()
    End Sub

    Protected Sub Change_Date(sender As System.Object, e As System.EventArgs)
      Dim strScript As String = "<script>window.opener.document.forms(0)." + control.Value + ".value = '"
                   strScript += calDate.SelectedDate.ToString("MM/dd/yyyy")
                   strScript += "';self.close()"
                   strScript += "</" + "script>"
      RegisterClientScriptBlock("anything",strScript)
    End Sub

  End Class

Now for our very simple test page (web form) which includes a user control containing two textboxes to hold dates. This test page is named GetUcDates.aspx.

<%@ Register TagPrefix="uc1" TagName="WithCalendar" Src="WithCalendar.ascx" %>
<%@ Page Language="vb" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>GetUcDates</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name=vs_defaultClientScript content="JavaScript">
<meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
  <uc1:WithCalendar id="WithCalendar1" runat="server"></uc1:WithCalendar>
</form>
</body>
</HTML>

Notice that the form tag is on the web form and not in the user control. This is so that you can have other controls within the form tags on the web form.

Finally we come to the user control itself. This is where we implement the technique which makes the popup calendar work within a user control. First I will show the code and then explain it. Before I do that, I will just point out that the user control contains two textboxes, txtStartDate and txtEndDate. The change we need to focus on is in the JavaScript.

<%@ Control Language="vb" AutoEventWireup="false" Codebehind="withcalendar.ascx.vb" Inherits="DotNetJohn.WithCalendar" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>

<table>
  <tr>
    <td align="right">
      Start Date:
    </td>
    <td align="left">
      <asp:TextBox ID="txtStartDate" Runat="server" ReadOnly="True" />
    </td>
    <td align="center">
      <a href="javascript:;" onclick="window.open('popcal.aspx?textbox=<%= id %>_txtStartDate','cal','width=250,height=225,left=270,top=180')">
      <img src="images/SmallCalendar.gif" border="0"></a>
    </td>
  </tr>
  <tr>
    <td align="right">
      End Date:
    </td>
    <td align="left">
      <asp:TextBox ID="txtEndDate" Runat="server" ReadOnly="True" />
    </td>
    <td align="center">
      <a href="javascript:;" onclick="window.open('popcal.aspx?textbox=<%= id %>_txtEndDate','cal','width=250,height=225,left=270,top=180')">
      <img src="images/SmallCalendar.gif" border="0"></a>
    </td>
  </tr>
</table>

Depending on your screen resolution, the lines containing the javascript may be difficult to read. It will be easier to read when you download the code. In the version that works on a web form and not a user control, part of the line of javascript read textbox=txtStartDate or textbox=txtEndDate. When you place the textboxes in a user control, .NET cannot "see" the textboxes in the user control, i.e. it does not have a reference. In the code included here we have the line textbox=<%= id %>_txtStartDate or txtEndDate. That "id" variable is actually the id we gave the user control on our web form (withcalendar1). We could have hard coded "withcalendar1" and it would work, but just grabing the id is a lot easier on us programmers.

Well I hope this helps some of you out there, and I'm sorry it took so long to come up with a solution to the problem. Thanks again to Ken Walker for his help.

You may download the code here.