The Calendar Control and the DayRender Event in ASP.Net

Sunday, August 22, 2004
In this article, we will use the Calendar control and DataGrid controls to display a calendar of events. The calendar will display small icons and highlight each day where an event occurs. When the user selects a date, the grid will show additional details for the events of selected day. A screen shot of the running web form is shown below.

We will first need a source of data. In this example we will use a DataTable, but you should pick what works best for your application. Our web form simulates a database query by populating a DataTable programmatically.

// to simulate a database query
socialEvents = new DataTable();
socialEvents.Columns.Add(new DataColumn("Date", typeof(DateTime)));
socialEvents.Columns.Add(new DataColumn("Description", typeof(string)));
socialEvents.Columns.Add(new DataColumn("Url", typeof(string)));

DataRow row;
row = socialEvents.NewRow();
row["Date"] = DateTime.Now.AddDays(-5);
row["Description"] = "Poker game at Scott's";
row["Url"] = "http://www.OdeToCode.com/blogs/scott/";
socialEvents.Rows.Add(row);
//
// add more rows… 
//

Unlike the DataGrid, the Calendar control has no built in ability to data bind, but the control does allow us to modify the format and content rendered by catching the DayRender event.

The DayRender event fires each time the calendar creates a table cell for the calendar table. The event has an argument of type DayRenderEventArgs. The argument has two properties, one property to represent the date for the cell, and one to represent the TableCell control. Let’s take a look at the event handler for the DayRender event.

private void Calendar1_DayRender(object sender, DayRenderEventArgs e)
{
   DataRow[] rows = socialEvents.Select(
         String.Format(
            "Date >= #{0}# AND Date < #{1}#", 
            e.Day.Date.ToShortDateString(),
            e.Day.Date.AddDays(1).ToShortDateString()
         )
      );

   foreach(DataRow row in rows)
   {                         
      System.Web.UI.WebControls.Image image;
      image = new System.Web.UI.WebControls.Image();
      image.ImageUrl = "dot.gif";
      image.ToolTip = row["Description"].ToString();
      e.Cell.Controls.Add(image);
      e.Cell.BackColor = Color.Firebrick;
   }
}

Our first step is to find out if there are any events for the current date. In the above code we are using the DataTable Select method to find matching records, but again you’ll have to adjust the algorithm to suit your application’s performance and scalability requirements. Depending on the size of the data and the number of users you need to support, the Select method may not be the best fit, but it is easy to use for this example.

We need to build a string for the Select expression that will look like the following.

			"Date >= #8/24/2004# AND Date < #8/25/2004#".
		

ADO.NET expressions require dates enclosed within # characters. Comparing dates can be a tricky problem, particularly when the underlying type, like the .NET DateTime type, includes time information. To truncate the time, we use the ToShortDateString method of the DateTime class.

Once we have found valid events, the next step is to modify the appearance of the cell containing the Calendar day. We will add a small icon (dot.gif) for each event by creating an Image control and adding the control to the Cell object’s Controls collection. You can only add static controls, like an Image or HyperLink to the cell, nut not dynamic event raising controls like a DropDownList or Button. We also change the background color of the cell to draw more attention to the date.

When a user selects a date in the Calendar by clicking on a day, the Calendar contol will fire the SelectionChanged event. We can catch this event in our code and display more details for the date selected.

private void Calendar1_SelectionChanged(object sender, System.EventArgs e)
{
   System.Data.DataView view = socialEvents.DefaultView;
   view.RowFilter = String.Format(
                     "Date >= #{0}# AND Date < #{1}#", 
                     Calendar1.SelectedDate.ToShortDateString(),
                     Calendar1.SelectedDate.AddDays(1).ToShortDateString()
                  );
                  
   if(view.Count > 0)
   {
      DataGrid1.Visible = true;
      DataGrid1.DataSource = view;
      DataGrid1.DataBind();
   }
   else
   {
      DataGrid1.Visible = false;
   }
}

In the code above, we again build an expression, but this time for the DataView Filter property. By setting the proper filter expression we can see only those rows in the DataTable matching the selected date. Simple binding this new view of the DataTable to the DataGrid will give us all the details of our events. In the ASPX page we set the DataGrid Visible property to false, and override this property in code only if there are events to display. The columns of the grid are defined as follows.

<Columns>
	<asp:BoundColumn DataField="Description" HeaderText="Description" />
	<asp:HyperLinkColumn DataTextField="Url" HeaderText="Link" NavigateUrl="Url" />
</Columns>

The files Socials.aspx and Socials.aspx.cs are available to download. To experiment with these files, create a new web project in Visual Studio. Right click on the project in the Solution Explorer window and select “Add Existing Item”. Browse to the Socials.aspx file to import the form into the project. This code should give you the basics to try your own calendar control experiments.

by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!