static void

ASP Calendar

This is my version of an asp calendar (as a UserControl here for simplicity). It doesn't postback - it's intended for static display only (if you need a datepicker, there are plenty of better javascript versions). The html is much simpler than the real calendar control and lends itself to css styling (each date cell has a css classes like "y2007 m01 d01" which make it easy to highlight e.g. 1st of every month, or a particular month among several calendars just with css rules). The DayRender event is exactly the same as the asp Calendar.

Code behind

using System;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
 
/// <summary>
/// Displays a localised Gregorian calendar. Similar to the <see cref="System.Web.UI.WebControls.Calendar"/> but with simpler markup and no selection/ postbacks. Use the <see cref="DayRender"/> event to add calendar "events".
/// </summary>
/// <remarks>
/// This is localized (month and day names, long date format) using the .Net framework.
/// <code>
///        CultureInfo culture = new CultureInfo("ja-JP");
///        System.Threading.Thread.CurrentThread.CurrentCulture = culture;
/// </code>
/// It won't do a Hebrew/he-IL or Japanese/ja-JP calendar, as DateTime always uses a Gregorian calendar (you would have to account for having 13 months).
/// </remarks>
/// <example>
/// Example css:
/// <code>
///  table { border-collapse: collapse; }
///  td { margin: 0; padding: 5px; border: 1px solid gray; text-align: right; vertical-align: top; }
///  .weekend { background-color: #bbb; }
///  .today { background-color: #ddd; }
/// </code>
/// Example use:
/// <code>
/// &lt;uc1:Calendar ID="Calendar1" runat="server" Date="2007/01/12" WeekendCssClass="weekend" TodayCssClass="today" OnDayRender="Calendar_DayRender" FirstDayOfWeek="Sunday" /&gt;
/// </code>
/// </example>
[DefaultEvent("DayRender"), DefaultProperty("Date")]
public partial class Calendar : System.Web.UI.UserControl
{
    #region Properties
 
    public string CssClass
    {
        get
        {
            object o = ViewState["CssClass"];
            return (o != null) ? (string)o : null;
        }
        set { ViewState["CssClass"] = value; }
    }
 
    public DateTime Date
    {
        get
        {
            object o = ViewState["Date"];
            return (o != null) ? (DateTime)o : DateTime.Today;
        }
        set { ViewState["Date"] = value; }
    }
 
    public DayOfWeek FirstDayOfWeek
    {
        get
        {
            object o = ViewState["FirstDayOfWeek"];
            return (o != null) ? (DayOfWeek)o : CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
        }
        set { ViewState["FirstDayOfWeek"] = value; }
    }
 
    public string HeaderRowCssClass
    {
        get
        {
            object o = ViewState["HeaderRowCssClass"];
            return (o != null) ? (string)o : null;
        }
        set { ViewState["HeaderRowCssClass"] = value; }
    }
 
    public bool ShowCaption
    {
        get
        {
            object o = ViewState["ShowCaption"];
            return (o != null) ? (bool)o : true;
        }
        set { ViewState["ShowCaption"] = value; }
    }
 
    public string TodayCssClass
    {
        get
        {
            object o = ViewState["TodayCssClass"];
            return (o != null) ? (string)o : null;
        }
        set { ViewState["TodayCssClass"] = value; }
    }
 
    public string WeekendCssClass
    {
        get
        {
            object o = ViewState["WeekendCssClass"];
            return (o != null) ? (string)o : null;
        }
        set { ViewState["WeekendCssClass"] = value; }
    }
 
    #endregion
 
    #region Events
 
    /// <summary>
    /// Occurs when a day is rendered. Exactly the same as asp:Calender.
    /// </summary>
    /// <example>
    /// <code>
    ///protected void Calendar_DayRender(object sender, DayRenderEventArgs e)
    ///{
    ///    if (e.Day.IsToday)
    ///    {
    ///        HtmlGenericControl para = new HtmlGenericControl("p");
    ///        para.InnerText = "Today";
    ///        e.Cell.Controls.Add(para);
    ///    }
    ///}
    /// </code>
    /// </example>
    public event DayRenderEventHandler DayRender;
 
    #endregion
 
    #region Methods
 
    protected void Page_Load(object sender, EventArgs e)
    {
        DrawCalendar(); //redraw for postbacks too
    }
 
    protected void DrawCalendar()
    {
        CultureInfo culture = CultureInfo.CurrentCulture;
        int firstDay = (int)FirstDayOfWeek;
 
        if (!string.IsNullOrEmpty(CssClass))
            CalendarTable.CssClass = CssClass;
 
        if (ShowCaption)
            CalendarTable.Caption = Date.ToString(culture.DateTimeFormat.YearMonthPattern, culture);
 
        CalendarTable.Rows.Clear(); //clear any presentation rows
        DrawWeekDayHeaders(culture);
 
        int daysInMonth = culture.Calendar.GetDaysInMonth(Date.Year, Date.Month);
        DateTime firstDayOfMonth = new DateTime(Date.Year, Date.Month, 1);
        int startWeekDay = (int)firstDayOfMonth.DayOfWeek;
 
        TableRow currentRow = new TableRow();
        CalendarTable.Rows.Add(currentRow);
        if (firstDay != startWeekDay)
        {
            int dayIndex = firstDay;
            int leadingDays = startWeekDay - firstDay;
            if (leadingDays < 0) leadingDays = 6 - firstDay + startWeekDay + 1;
            for (int i = 0; i < leadingDays; i++)
            {
                currentRow.Cells.Add(new TableCell());
            }
        }
 
        DateTime date = firstDayOfMonth;
        for (int i = 1; i <= daysInMonth; i++)
        {
            DrawDay(currentRow, date);
 
            date = date.AddDays(1);
            if (date.Day == daysInMonth)
                break;
            if (date.DayOfWeek == FirstDayOfWeek)
            {
                currentRow = new TableRow();
                CalendarTable.Rows.Add(currentRow);
            }
        }
        //fill rest of week
        for (int i = 0; i < 6; i++)
        {
            if ((int)date.DayOfWeek == firstDay)
                break;
            TableCell cell = new TableCell();
            cell.ToolTip = date.ToLongDateString();
            currentRow.Cells.Add(cell);
            date = date.AddDays(1);
        }
    }
 
    protected void DrawDay(TableRow currentRow, DateTime date)
    {
        string dateString = date.ToString("dd", CultureInfo.CurrentCulture);
        bool isWeekend = (date.DayOfWeek == DayOfWeek.Saturday) || (date.DayOfWeek == DayOfWeek.Sunday);
        bool isToday = date.Equals(DateTime.Today);
 
        TableCell cell = new TableCell();
        string cssClass = "y" + date.Year + " m" + date.ToString("MM", CultureInfo.CurrentCulture) + " d" + dateString;
        cell.CssClass = cssClass +
            (isWeekend ? " " + WeekendCssClass : string.Empty)
            + (isToday ? " " + TodayCssClass : string.Empty);
        Label lab = new Label();
        lab.Text = dateString;
        lab.ToolTip = date.ToLongDateString();
        cell.Controls.Add(lab);
        DayRenderEventHandler dayRender = DayRender;
        if (dayRender != null)
        {
            var day = new CalendarDay(date,
                isWeekend,
                isToday,
                false, //this is never selectable
                false, //this is never another month
                dateString);
            var eventArgs = new DayRenderEventArgs(cell, day);
            dayRender(this, eventArgs);
        }
        currentRow.Cells.Add(cell);
    }
 
    protected void DrawWeekDayHeaders(CultureInfo culture)
    {
        TableHeaderRow row = new TableHeaderRow();
        CalendarTable.Rows.Add(row);
        if (!string.IsNullOrEmpty(HeaderRowCssClass)) row.CssClass = HeaderRowCssClass;
 
        int firstDay = (int)culture.DateTimeFormat.FirstDayOfWeek;
        string[] abbreviatedDayNames = culture.DateTimeFormat.AbbreviatedDayNames;
        int dayIndex = firstDay;
        for (int i = 0; i < 7; i++)
        {
            TableHeaderCell cell = new TableHeaderCell();
            row.Controls.Add(cell);
            cell.Text = abbreviatedDayNames[dayIndex];
            dayIndex++;
            if (dayIndex > 6) dayIndex = 0;
        }
    }
 
    /// <summary>
    /// Renders to HTML. Use this method for Ajax postbacks.
    /// </summary>
    /// <returns>A string of html suitable for ajax.</returns>
    public string RenderToHtml()
    {
        StringBuilder sb = new StringBuilder();
        using (StringWriter sw = new StringWriter(sb))
        {
            using (HtmlTextWriter textWriter = new HtmlTextWriter(sw))
            {
                this.RenderControl(textWriter);
            }
        }
        return sb.ToString();
    }
 
    #endregion
}

Page

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Calendar.ascx.cs" Inherits="Calendar" %>
<asp:Table runat="server" ID="CalendarTable">
    <asp:TableHeaderRow>
        <asp:TableHeaderCell Text="M" />
        <asp:TableHeaderCell Text="T" />
        <asp:TableHeaderCell Text="W" />
        <asp:TableHeaderCell Text="T" />
        <asp:TableHeaderCell Text="F" />
        <asp:TableHeaderCell Text="S" />
        <asp:TableHeaderCell Text="S" />
    </asp:TableHeaderRow>
    <asp:TableRow>
        <asp:TableCell Text=" " />
        <asp:TableCell Text=" " />
        <asp:TableCell Text="1" />
        <asp:TableCell Text="2" />
        <asp:TableCell Text="3" />
        <asp:TableCell Text="4" />
        <asp:TableCell Text="5" />
    </asp:TableRow>
</asp:Table>