Sample Project

The sample project includes:

Online Demo


Visual Studio 2010 Solution

  • .NET Framework 4.0 or higher
  • Visual Studio 2010 or higher (optional)
  • Microsoft SQL Server 2008+ (Express) 

Visual Studio 2012 Solution

  • .NET Framework 4.0 or higher
  • Visual Studio 2012 or higher (optional)
  • Microsoft SQL Server 2012 (Express) 


This tutorial shows how to create an AJAX timetable in an ASP.NET web application. It supports custom time slots (blocks), drag&drop event moving and resizing, and custom event colors.

  • Weekly timetable view
  • Displays time slots (blocks) with custom size (block number is mapped to the hour component of the DateTime)
  • Inline editing of the block properties using active areas.
  • Custom event color in combination with CssOnly mode (CSS styling).
  • Loads events and blocks from SQL Server database.
  • Full calendar CSS styling (calendar_green theme).
  • Integrates DayPilot Navigator for switching the week.
  • C# and VB.NET source code included.
  • Sample database included.


Licensed for testing and evaluation purposes. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for ASP.NET WebForms. Buy a license.


This tutorial doesn't cover DayPilot Calendar basics. For more information about  configuring the week view, loading events from a database or enabling the AJAX drag and drop operations (moving, resizing) please see the following tutorial:

1. Mapping Timetable Slots to Hours

Internally, the Calendar control works with time slots of equal size. The maximum supported slot size is 60 minutes (CellDuration property).

In order to show a timetable with custom blocks, it is necessary to map the block to the hour part of the DateTime. This allows a maximum of 24 slots per day. It would be possible to map it to the minute part as well if needed (modify TimetableManager.cs/TimetableManager.vb class).

Day (February 1, 2013)

  • Block 1 => mapped as 2013-02-01T01:00:00
  • Block 2 => mapped as 2013-02-01T02:00:00
  • etc.

Day 2 (February 2, 2013)

  • Block 1 => mapped as 2013-02-02T01:00:00
  • Block 2 => mapped as 2013-02-02T02:00:00
  • etc.

We will limit the display to 7 time slots (using DayBeginsHour, DayEndsHour, HeightSpec properties), each taking one hour (CellDuration property). We will increase the default time cell size to 70 pixels (CellHeight property):


Now we will use BeforeTimeHeaderRender to customize the time headers (vertical axis). We will replace the default text with the block name (start and end) as defined in the database. The real block start and end times are defined in [Block] database table:

The block start and end times (BlockStart, BlockEnd) are stored as DateTime fields but only the time part is significant.

Our BeforeTimeHeaderRender handler looks like this:


protected void DayPilotCalendar1_OnBeforeTimeHeaderRender(BeforeTimeHeaderRenderEventArgs ea)
    int id = ea.Start.Hours;
    DataRow r = FindBlock(id);
    ea.InnerHTML = String.Format("Block {0}<br/>{1}<br/>{2}", id, TimeFormatter.GetHourMinutes((DateTime)r["BlockStart"], DayPilotCalendar1.TimeFormat), TimeFormatter.GetHourMinutes((DateTime)r["BlockEnd"], DayPilotCalendar1.TimeFormat));


Protected Sub DayPilotCalendar1_OnBeforeTimeHeaderRender(ByVal ea As BeforeTimeHeaderRenderEventArgs)
	Dim id As Integer = ea.Start.Hours
	Dim r As DataRow = FindBlock(id)
	ea.InnerHTML = String.Format("Block {0}<br/>{1}<br/>{2}", id, TimeFormatter.GetHourMinutes(CDate(r("BlockStart")), DayPilotCalendar1.TimeFormat), TimeFormatter.GetHourMinutes(CDate(r("BlockEnd")), DayPilotCalendar1.TimeFormat))
End Sub

It will replace the default header text (e.g. "1 AM") with the block details:

2. Timetable Block Editing

We will make the block properties (start and end time) editable by adding an active area to each time header cell:

The active area is added in BeforeTimeHeaderRender event handler:


protected void DayPilotCalendar1_OnBeforeTimeHeaderRender(BeforeTimeHeaderRenderEventArgs ea)
	// ...

	ea.Areas.Add(new Area().Width(15).Top(0).Bottom(0).Right(0).CssClass("resource_action_menu").Html("<div><div></div></div>").JavaScript("editBlock(e);"));


Protected Sub DayPilotCalendar1_OnBeforeTimeHeaderRender(ByVal ea As BeforeTimeHeaderRenderEventArgs)
	Rem ...
	ea.Areas.Add((New Area()).Width(15).Top(0).Bottom(0).Right(0).CssClass("resource_action_menu").Html("<div><div></div></div>").JavaScript("editBlock(e);"))
End Sub

It specifies the area dimensions, CSS class and associated action. This active area will execute editBlock() JavaScript method when clicked. The editBlock() methods opens a dialog box with block details:

3. Custom Timetable Event Colors

The new event dialog (NewDialog.aspx) allows users to add events to the timetable and specify event properties, including description and color.

Blocks are loaded from the database:



private void FillDropDownListStart()
	DataTable blocks = new DataManager().GetBlocks();

	foreach(DataRow r in blocks.Rows)
		int id = Convert.ToInt32(r["BlockId"]);
		DateTime start = (DateTime) r["BlockStart"];
		DateTime end = (DateTime)r["BlockEnd"];
		string name = String.Format("Block {0} ({1} - {2})", id, TimeFormatter.GetHourMinutes(start, TimeFormat.Auto), TimeFormatter.GetHourMinutes(end, TimeFormat.Auto));
		ListItem item = new ListItem(name, id.ToString());


Private Sub FillDropDownListStart()
	Dim blocks As DataTable = (New DataManager()).GetBlocks()

	For Each r As DataRow In blocks.Rows
		Dim id As Integer = Convert.ToInt32(r("BlockId"))
		Dim start As Date = CDate(r("BlockStart"))
		Dim [end] As Date = CDate(r("BlockEnd"))
		Dim name As String = String.Format("Block {0} ({1} - {2})", id, TimeFormatter.GetHourMinutes(start, TimeFormat.Auto), TimeFormatter.GetHourMinutes([end], TimeFormat.Auto))
		Dim item As New ListItem(name, id.ToString())
	Next r
End Sub



public DataTable GetBlocks()
	var da = CreateDataAdapter("select * from [Block] order by [BlockId]");
	DataTable dt = new DataTable();
	return dt;


Public Function GetBlocks() As DataTable
	Dim da = CreateDataAdapter("select * from [Block] order by [BlockId]")
	Dim dt As New DataTable()
	Return dt
End Function

The event details are saved in [Assignment] table:

The event color field (AssignmentColor) is used to store the event color. This field can't be mapped to the event color directly but we can do it in BeforeEventRender event handler:


protected void DayPilotCalendar1_BeforeEventRender(object sender, DayPilot.Web.Ui.Events.Calendar.BeforeEventRenderEventArgs e)
	string color = (string) e.DataItem["AssignmentColor"];
	if (!String.IsNullOrEmpty(color))
		e.BackgroundColor = color;
		e.BorderColor = color;
		e.FontColor = "#ffffff";


Protected Sub DayPilotCalendar1_BeforeEventRender(ByVal sender As Object, ByVal e As DayPilot.Web.Ui.Events.Calendar.BeforeEventRenderEventArgs)
	Dim color As String = CStr(e.DataItem("AssignmentColor"))
	If Not String.IsNullOrEmpty(color) Then
		e.BackgroundColor = color
		e.BorderColor = color
		e.FontColor = "#ffffff"
	End If
End Sub