Article
Beginning ASP.NET Using VB.NET - Chapter 14: ASP.NET Server Controls
Once you've completed all the steps for entering the controls and code, you should be able to load the MyCalendar.aspx file into your browser. You should see the following display served up after the page loads:

How It Works
The first step in creating the MyCalendar.aspx web form was to define what we wanted it to do, which was this: given a custom XML file with various calendar event data (MyCalendar.xml), load each of the event items in an ASP.NET Calendar control. In steps 1 through 4, above, we basically created an ASPX page that defined three different ASP.NET server controls: Calendar, Repeater and Panel.
Calendar Implementation Details
The Calendar control serves as the primary visual interface for the user. We set a host of properties to customize the look of the control -- see step 2 for details. The first question you might be wondering is, why does the Calendar control default to July 2001, and why is the date July 17, 2001 selected by default? It comes down to the following code:
<asp:Calendar id="MyCalendar" runat="server"
SelectedDate="2001/07/17"
VisibleDate="2001/07/01"
The SelectedDate property is used to set the date that the calendar will default to when first opened. The VisibleDate property sets the month of the calendar that is visible, for example, defining the date "2001/08/01" will make the month August of 2001 visible.
As previously mentioned, the SelectedDate and VisibleDate properties were set this way for demonstration purposes only, since the entries in the MyCalendar.xml file only have calendar data for this particular time span.
When we declared the Calendar control, we assigned event handlers for two of the Calendar controls events:
<asp:Calendar id="MyCalendar" runat="server"
...
OnDayRender="MyCalendar_DayRender"
OnSelectionChanged="MyCalendar_SelectionChanged">
...
The MyCalendar_DayRender event is invoked whenever the Calendar control begins to display a day that will be visible, and the MyCalendar_SelectionChanged event is invoked when a new date is selected. Our Calendar control displays six weeks worth of data -- the days representing the month being displayed, as well as a share of days from the previous and next months. In order to give our Calendar control a unique look, we implemented a bit of logic to determine if the day being rendered was part of another month (IsOtherMonth), a weekend day (IsWeekEnd), or if the day was part of the month being displayed. The logic for displaying the various Calendar Cell color formatting is demonstrated in this code fragment (from step 8):
Protected Sub MyCalendar_DayRender(ByVal Sender As System.Object, _
ByVal e As DayRenderEventArgs )
if ( e.Day.IsOtherMonth )
e.Cell.BackColor=System.Drawing.Color.FromName("Gainsboro")
Else If ( e.Day.IsWeekend )
e.Cell.BackColor=System.Drawing.Color.FromName("PaleGoldenrod")
Else
e.Cell.BackColor=System.Drawing.Color.FromName(
"LightGoldenrodYellow")
End if
...
End Sub
The way this code works is that we use an if statement to determine whether the day being called is a month, for example, if ( e.Day.IsOtherMonth ). If this statement is true, we define the backcolour of that Cell by importing the System.Drawing namespace, and requesting the color we want. The variable e is automatically passed into this event procedure by ASP.NET. It contains additional information about the control that might be useful to a programmer. In our case we use it to set the color of the Cell (which represents a day).
The next step in rendering the MyCalendar.xml data to a given Calendar Cell involved loading the XML data source into a DataSet. What might not be obvious is the use of the Session object to store a cached instance of the loaded DataSet. The reason for caching the DataSet object, is so that we can reduce the number of times the calendar data (stored in the MyCalendar.xml file) is loaded from scratch. The DataSet object will be cached for the lifetime of the session.
In step 7, before we attempted to load the file, we first checked the Session object for an instance of a MyCalendarData object, which is a DataSet object. If there's already one declared, there's no need to perform the work of loading in the XML file again -- the cachedData object is returned. If Session("MyCalendarData") returns Nothing, then we perform the work of loading the XML source, but once we're done loading it, we assign the dataset to the Session("MyCalendarData") object:
Protected Function LoadMyCalendarData() As DataSet
...
Dim cachedDataSet as DataSet = Session("MyCalendarData")
if ( Not cachedDataSet Is Nothing ) Then
Return cachedDataSet
End if
...
Try
fileStream = New FileStream(sourceXML, FileMode.Open)
dataSet.ReadXml(fileStream)
fileStream.Close()
Session("MyCalendarData") = dataSet
...
End Function
In using the DataSet from the Session object, we don't need to load the MyCalendar.xml file from scratch each time the Calendar control renders a day item. Keep in mind that the Calendar control renders 6 weeks worth of days, which amounts to 42 calls (6 weeks times 7 days in a week) to the LoadMyCalendarData method on a single page load -- so even though the LoadMyCalendar method is being invoked numerous times, it's optimized to use the cached DataSet stored in Session ("MyCalendarData").