Including a Popup Calendar Inside an ASP.NET Datagrid...

You can include a popup calendar for date textboxes in an ASP.NET datagrid while in edit mode.


By: John Kilgo Date: February 22, 2004 Download the code.

In previous articles we have shown ways to include a popup calendar for web forms. In this article we will demonstrate how to do it within an asp.net datagrid. The actual technique is about the same. You just have to know how to setup the datagrid and the codebehind to accomodate it. We will get right to the code without a hugh amount of explanation as most of it is fairly straightforward.

We are using the Orders table in the Northwind database for this example. It is not a particularly logical table to use, but it will do for demonstration purposes. The .aspx code for the example program (DGPopupCal.aspx) follows. What you should notice is that we are using TemplateColumns and that in the EditItemTemplate within the TemplateColumn for OrderDate we have included a linkbutton to show a small calendar image while in edit mode. That line is highlighted in red in the code below. That is all we need to do in the .aspx page to make our datagrid ready for the popup calendar. The actual code to implement it comes in the codebehind file. The id of the linkbutton is important as we will need to find the button in the codebehind page.

<%@ Page Language="vb" AutoEventWireup="false" Codebehind="DGPopupCal.aspx.vb" Inherits="DotNetJohn.DGPopupCal"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>DGPopupCal</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:datagrid id="dtgOrders"
              runat="server"
              BorderStyle="Ridge"
              BorderColor="LightGray"
              BorderWidth="1px"
              DataKeyField="OrderID"
              AutoGenerateColumns="False"
              HeaderStyle-Wrap="false"
              HeaderStyle-Font-Bold="True"
              HeaderStyle-BackColor="LightGrey"
              AlternatingItemStyle-BackColor="LightGrey"
              CellPadding="2"
              GridLines="Horizontal"
              Width="500px">
  <EditItemStyle BackColor="Coral"></EditItemStyle>
  <HeaderStyle Font-Bold="True" Wrap="False" BackColor="LightGray"></HeaderStyle>
  <Columns>
    <asp:TemplateColumn HeaderText="Customer ID">
      <ItemStyle HorizontalAlign="Left"></ItemStyle>
      <ItemTemplate>
        <asp:Label id="lblCustomerID" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.CustomerID", "") %>'>
        </asp:Label>
      </ItemTemplate>
      <EditItemTemplate>
        <asp:TextBox id="tbCustomerID" runat="server" Width="65px" Text='<%# DataBinder.Eval(Container, "DataItem.CustomerID", "") %>'>
        </asp:TextBox>
      </EditItemTemplate>
    </asp:TemplateColumn>
    <asp:TemplateColumn HeaderText="Employee ID">
      <ItemStyle HorizontalAlign="Left"></ItemStyle>
      <ItemTemplate>
        <asp:Label id="lblEmployeeID" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.EmployeeID", "") %>'>
        </asp:Label>
      </ItemTemplate>
      <EditItemTemplate>
        <asp:TextBox id="txtEmployeeID" runat="server" Width="65px" Text='<%# DataBinder.Eval(Container, "DataItem.EmployeeID", "") %>'>
        </asp:TextBox>
      </EditItemTemplate>
    </asp:TemplateColumn>
    <asp:TemplateColumn HeaderText="Order Date">
      <ItemTemplate>
        <asp:Label id="lblOrderDate" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.OrderDate", "{0:d}") %>'>
        </asp:Label>
      </ItemTemplate>
      <EditItemTemplate>
        <asp:TextBox id="txtOrderDate" runat="server" Width="75px" Text='<%# DataBinder.Eval(Container, "DataItem.OrderDate", "{0:d}") %>' ReadOnly="True">
        </asp:TextBox> 
        <asp:HyperLink id="lbtnCalendar" runat="server" ImageUrl="images/smallcalendar.gif"></asp:HyperLink>
      </EditItemTemplate>
    </asp:TemplateColumn>
    <asp:TemplateColumn>
      <ItemTemplate>
        <asp:LinkButton id="lbtnEdit" runat="server" Text="<img border=0 src=images/dtg_edit.gif alt=edit>" CommandName="Edit"></asp:LinkButton>
      </ItemTemplate>
      <EditItemTemplate>
        <asp:LinkButton id="lbtnUpdate" runat="server" Text="<img border=0 src=images/dtg_update.gif alt=save/update>" CommandName="Update"></asp:LinkButton> 
        <asp:LinkButton id="lbtnCancel" runat="server" Text="<img border=0 src=images/dtg_cancel.gif alt=cancel>" CommandName="Cancel"></asp:LinkButton>
      </EditItemTemplate>
    </asp:TemplateColumn>
  </Columns>
</asp:datagrid></P>
</form>
</body>
</html>

The codebehind file is shown below. The majority of it is the usual code to get the data from the database table, put the datagrid in edit, update, or cancel mode, and to update the table with new data. I won't go through it all here. What you should take notice of, however, is the ItemDataBound event (the last subroutine in the code). It is here that we find the clientID for the date textbox and call the popup calendar using javascript. There is also javascript in the popup calendar (DGCal.aspx). I have not shown the code for DGCal.aspx/.vb, but it is included in the download for this article. Note that we are finding the "txtOrderDate" textbox in this example. You will have to change that name for your own implementation.

Also notice that part of the dtgOrders_Update routine has been commented out. I cannot allow you to actually change the data in a Northwind table on my host's machine. You can uncomment the lines after you download the code, and the update will be performed properly.

Below is the complete code for the codebehind file.

Imports System.Data.SqlClient
Imports System.Configuration

Public Class DGPopupCal
  Inherits System.Web.UI.Page
  Protected WithEvents dtgOrders As System.Web.UI.WebControls.DataGrid

  Dim dataSet As dataSet

  ' " Web Form Designer Generated Code " Omitted

  Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    If Not IsPostBack Then
      GetData()
    End If
  End Sub

  Private Sub GetData()
    Dim objConn As New SqlConnection(ConfigurationSettings.AppSettings("NorthwindConnection"))
    Dim objCmd As New SqlCommand
    Dim dataAdapter As SqlDataAdapter

    objCmd.Connection = objConn
    objCmd.CommandType = CommandType.Text
    objCmd.CommandText = "SELECT Top 10 OrderID, CustomerID, EmployeeID, OrderDate FROM Orders"

    objConn.Open()

    dataAdapter = New SqlDataAdapter
    dataAdapter.TableMappings.Add("Table", "Orders")
    dataAdapter.SelectCommand = objCmd

    dataSet = New DataSet("Orders")
    dataAdapter.Fill(dataSet)
    dtgOrders.DataSource = dataSet
    dtgOrders.DataBind()

    objConn.Dispose()
  End Sub

  Sub dtgOrders_Edit(ByVal sender As Object, ByVal e As DataGridCommandEventArgs) Handles dtgOrders.EditCommand
    dtgOrders.EditItemIndex = CInt(e.Item.ItemIndex)
    GetData()
  End Sub

  Sub dtgOrders_Cancel(ByVal sender As Object, ByVal e As DataGridCommandEventArgs) Handles dtgOrders.CancelCommand
    dtgOrders.EditItemIndex = -1
    GetData()
  End Sub

  Sub dtgOrders_Update(ByVal sender As Object, ByVal e As DataGridCommandEventArgs) Handles dtgOrders.UpdateCommand
    Dim OrderID As Int32
    Dim CustomerID As String
    Dim EmployeeID As Int32
    Dim OrderDate As String

    OrderID = Convert.ToInt32(dtgOrders.DataKeys(CInt(e.Item.ItemIndex)))
    CustomerID = Convert.ToString(CType(e.Item.FindControl("tbCustomerID"), TextBox).Text)
    OrderDate = Convert.ToString(CType(e.Item.FindControl("txtOrderDate"), TextBox).Text)
    EmployeeID = Convert.ToInt32(CType(e.Item.FindControl("txtEmployeeID"), TextBox).Text)

    Dim strSQL As String
    strSQL = "UPDATE Orders SET " _
          & "CustomerID='" & CustomerID & "', " _
          & "EmployeeID=" & EmployeeID & ", " _
          & "OrderDate='" & OrderDate & "' " _
          & "WHERE OrderID=" & OrderID

    'Dim objConn As New SqlConnection(ConfigurationSettings.AppSettings("NorthwindConnection"))
    'Dim objCmd As New SqlCommand

    'objCmd.Connection = objConn
    'objCmd.CommandType = CommandType.Text
    'objCmd.CommandText = strSQL

    'objConn.Open()

    'objCmd.ExecuteNonQuery()

    'objConn.Dispose()

    dtgOrders.EditItemIndex = -1
    GetData()
  End Sub

  Private Sub dtgOrders_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dtgOrders.ItemDataBound

    If e.Item.ItemType = ListItemType.EditItem Then
      Dim strTextBoxName As String = e.Item.Cells(0).FindControl("txtOrderDate").ClientID()
      CType(e.Item.FindControl("lbtnCalendar"), HyperLink).NavigateUrl = "javascript:calendar_window=window.open('DGCal.aspx?formname=Form1." & strTextBoxName & "','DatePicker','width=250,height=190,left=360,top=180');calendar_window.focus();"
    End If

  End Sub

End Class

I hope this example will put another trick in your bag. Implementing the popup calendar is really not very hard to do. Best of luck with it.

You may run the example program here. (Remember that the data will not actually update with this version).
You may download the code here.