I am looking for a asp.net control that will display a full year in a grid format, with each month as a row and each day in the month as the columns. I have found the follow
Whipped up this, just for you:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Yearly Calendar</title>
<style type="text/css">
table td { padding:0; margin:0; border:1px solid #dadada; }
table th { width:25px; text-align:center; }
table td { text-align:center; }
table td span { color:#dadada; }
table td a { color:#000000; text-decoration:none; }
table td a:hover { text-decoration:underline; }
table td a.hasEvents { color:#ff0000; }
table td a.selected { color:#0000ff; font-weight:bold; }
table td.month { background-color:#999999; }
table td.weekend { background-color:#D0D0D0; }
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th>
<asp:Literal ID="litSelectedYear" runat="server" />
</th>
<% for (int iWeek = 1; iWeek <= 6; iWeek++) {
for (int iDay = 1; iDay <= 7; iDay++) { if (iWeek == 6 && iDay > 2) break; %>
<th>
<%= GetDayName(iDay) %>
</th>
<% } } %>
</tr>
</thead>
<asp:Repeater ID="repMonths" runat="server" OnInit="repMonths_OnInit" OnItemDataBound="repMonths_OnItemDataBound">
<ItemTemplate>
<tr>
<td class="month">
<asp:HyperLink ID="hylMonth" runat="server" />
</td>
<asp:Repeater ID="repDays" runat="server" OnItemDataBound="repDays_OnItemDataBound">
<ItemTemplate>
<td id="tdDay" runat="server">
<asp:Literal ID="litDay" runat="server" />
</td>
</ItemTemplate>
</asp:Repeater>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
</div>
</form>
</body>
</html>
using System;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
private DateTime _dtMonth;
private DateTime _selectedDate;
private bool _specialDaySelected = true;
private int _currentBindingMonth;
protected void repMonths_OnInit(object sender, EventArgs e)
{
if (!DateTime.TryParse(Request.QueryString["CalDate"], out _selectedDate))
{
_specialDaySelected = false;
int selectedMonth, selectedYear;
int.TryParse(Request.QueryString["CalYear"], out selectedYear);
int.TryParse(Request.QueryString["CalMonth"], out selectedMonth);
if (selectedYear <= 0) selectedYear = DateTime.Now.Year;
if (selectedMonth <= 1) selectedMonth = 1;
else if (selectedMonth > 12) selectedMonth = 12;
_selectedDate = new DateTime(selectedYear, selectedMonth, 1);
}
litSelectedYear.Text = _selectedDate.Year.ToString();
repMonths.DataSource = new int[]{1,2,3,4,5,6,7,8,9,10,11,12};
repMonths.DataBind();
}
protected void repMonths_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Repeater repDays = (Repeater)e.Item.FindControl("repDays");
HyperLink hylMonth = (HyperLink)e.Item.FindControl("hylMonth");
_currentBindingMonth = (int)e.Item.DataItem;
_dtMonth = new DateTime(_selectedDate.Year, _currentBindingMonth, 1);
hylMonth.Text = _dtMonth.ToString("MMM");
hylMonth.NavigateUrl = string.Format("{0}?CalMonth={1}&CalYear={2}", Request.Path, _currentBindingMonth, _selectedDate.Year);
if (_currentBindingMonth == _selectedDate.Month) hylMonth.Attributes.Add("class", "selected");
if (_dtMonth.DayOfWeek != DayOfWeek.Monday)
{
int daysToSubtract = -(int)_dtMonth.DayOfWeek;
if (_dtMonth.DayOfWeek == DayOfWeek.Sunday) daysToSubtract = -7; // Special case. US weeks start with sunday, thus the enum DayOfWeek.Sunday = 0.
_dtMonth = _dtMonth.AddDays(daysToSubtract + 1);
}
DateTime[] dates = new DateTime[37];
for (int i = 0; i < 37; i++)
{
dates[i] = _dtMonth;
_dtMonth = _dtMonth.AddDays(1);
}
repDays.DataSource = dates;
repDays.DataBind();
}
}
protected void repDays_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
DateTime date = (DateTime)e.Item.DataItem;
Literal litDay = (Literal)e.Item.FindControl("litDay");
HtmlTableCell tdDay = (HtmlTableCell)e.Item.FindControl("tdDay");
if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday)
tdDay.Attributes.Add("class", "weekend");
if (_currentBindingMonth == date.Month)
litDay.Text = string.Format("<a href=\"{0}?CalDate={3}-{2}-{1}\"{4}>{3}</a>", Request.Path, date.Year, date.Month, date.Day.ToString("D2"), (_specialDaySelected && date.Equals(_selectedDate)) ? " class=\"selected\"" : string.Empty);
else
litDay.Text = string.Format("<span>{0}</span>", date.Day.ToString("D2"));
// Clear ID's
tdDay.ID = string.Empty;
}
}
public static string GetDayName(int dayInWeek)
{
switch (dayInWeek)
{
case 1: return "mo";
case 2: return "tu";
case 3: return "we";
case 4: return "th";
case 5: return "fr";
case 6: return "sa";
case 7: return "su";
}
return "God only made seven days in a week.";
}
}
You could build that with a combination of ASP.NET controls, such as two repeaters, one to render the months and one to render the days. It's possible to do it that way. It may be more difficult to include the other days of the month and to include the day of the week as depicted there, but its definitely possible.
The inner repeater binds the days, and the outer repeater binds the months.
An alternative may be to dynamically create a DataTable class and put all the logic to display the months within the table. Create as columns in the datatable the days, and create a new row for each month. That would work out too.
HTH.