This tutorial shows how to display a Gantt chart in ASP.NET MVC using DayPilot Pro ASP.NET MVC scheduler AJAX control.
Includes
Visual Studio solution
C# project with source code
VB.NET project with source code
Sample Microsoft SQL Server database
License
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 MVC.
Features
Gantt chart (one task/event per row)
Event duration displayed in an additional header column
Drag and drop moving and resizing
Modal dialog for event editing
Highlighting weekends
Razor views
See also ASP.NET MVC 5 Gantt Chart Tutorial - it shows how to use the new ASP.NET MVC Gantt chart control from DayPilot Pro for ASP.NET MVC.
See Also
Gantt Chart for ASP.NET WebForms Tutorial (ASP.NET, SQL Server, C#, VB.NET)
Setup
Include DayPilot.Web.Mvc.dll in the project.
Add daypilot-all.min.js javascript library.
<script src="@Url.Content("~/Scripts/DayPilot/daypilot-all.min.js")" type="text/javascript"></script>
Add Gantt Chart to MVC View
C# (Index.cshtml)
@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig
{
BackendUrl = Url.Content("~/Gantt/Backend"),
EventResizeHandling = EventResizeHandlingType.CallBack,
EventMoveHandling = EventMoveHandlingType.CallBack,
EventClickHandling = EventClickHandlingType.JavaScript,
EventClickJavaScript = "edit(e.id())",
TimeRangeSelectedHandling = TimeRangeSelectedHandlingType.JavaScript,
TimeRangeSelectedJavaScript = "create(start, end)",
CellGroupBy = GroupBy.Month,
CellDuration = 1440,
Days = 365,
StartDate = new DateTime(DateTime.Today.Year, 1, 1),
Theme = "scheduler_8",
EventHeight = 25,
CellWidth = 25,
MoveBy = DragArea.Full,
HeaderColumns = new RowHeaderColumnCollection {
new RowHeaderColumn("Task", 100),
new RowHeaderColumn("Duration", 100)
}
})
VB.NET (Index.vbhtml)
@Html.DayPilotScheduler("dps", New DayPilotSchedulerConfig With
{
.BackendUrl = Url.Content("~/Gantt/Backend"),
.EventResizeHandling = EventResizeHandlingType.CallBack,
.EventMoveHandling = EventMoveHandlingType.CallBack,
.EventClickHandling = EventClickHandlingType.JavaScript,
.EventClickJavaScript = "edit(e.id())",
.TimeRangeSelectedHandling = TimeRangeSelectedHandlingType.JavaScript,
.TimeRangeSelectedJavaScript = "create(start, end)",
.CellGroupBy = GroupBy.Month,
.CellDuration = 1440,
.Days = 365,
.StartDate = New DateTime(DateTime.Today.Year, 1, 1),
.Theme = "scheduler_8",
.EventHeight = 25,
.CellWidth = 25,
.MoveBy = DragArea.Full,
.HeaderColumns = New RowHeaderColumnCollection From {
New RowHeaderColumn("Task", 100),
New RowHeaderColumn("Duration", 100)
}
})
MVC Gantt Controller
This controller will handle AJAX requests from the client.
C# (GanttController.cs)
public class GanttController : Controller
{
public ActionResult Backend()
{
return new Dps().CallBack(this);
}
class Dps : DayPilotScheduler
{
protected override void OnInit(InitArgs e)
{
UpdateWithMessage("Welcome!", CallBackUpdateType.Full);
}
protected override void OnFinish()
{
if (UpdateType == CallBackUpdateType.None)
{
return;
}
Events = new EventManager().FilteredData(StartDate, StartDate.AddDays(Days)).AsEnumerable();
Resources.Clear();
Resources.Add("New Task", "NEW");
foreach (DataRow ev in Events)
{
Resource r = new Resource((string)ev["name"], Convert.ToString(ev["id"]));
r.DataItem = ev;
Resources.Add(r);
}
DataIdField = "id";
DataTextField = "name";
DataStartField = "eventstart";
DataEndField = "eventend";
DataResourceField = "id";
}
}
}
VB.NET (GanttController.vb)
Public Class GanttController
Inherits Controller
Public Function Backend() As ActionResult
Return (New Dps()).CallBack(Me)
End Function
Private Class Dps
Inherits DayPilotScheduler
Protected Overrides Sub OnInit(ByVal e As InitArgs)
UpdateWithMessage("Welcome!", CallBackUpdateType.Full)
End Sub
Protected Overrides Sub OnFinish()
If UpdateType = CallBackUpdateType.None Then
Return
End If
Events = (New EventManager()).FilteredData(StartDate, StartDate.AddDays(Days)).AsEnumerable()
Resources.Clear()
Resources.Add("New Task", "NEW")
For Each ev As DataRow In Events
Dim r As New Resource(CStr(ev("name")), Convert.ToString(ev("id")))
r.DataItem = ev
Resources.Add(r)
Next ev
DataIdField = "id"
DataTextField = "name"
DataStartField = "eventstart"
DataEndField = "eventend"
DataResourceField = "id"
End Sub
End Class
End Class
Display Task Duration in the Header
Define the row header columns for the Gantt chart.
C# (Index.cshtml)
@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig
{
BackendUrl = Url.Content("~/Gantt/Backend"),
...
HeaderColumns = new RowHeaderColumnCollection {
new RowHeaderColumn("Task", 100),
new RowHeaderColumn("Duration", 100)
}
})
VB.NET (Index.vbhtml)
@Html.DayPilotScheduler("dps", New DayPilotSchedulerConfig With
{
.BackendUrl = Url.Content("~/Gantt/Backend"),
...
.HeaderColumns = New RowHeaderColumnCollection From {
New RowHeaderColumn("Task", 100),
New RowHeaderColumn("Duration", 100)
}
})
Add duration values to the Gantt row header cells using OnBeforeResHeaderRender() method.
C# (GanttController.cs)
protected override void OnBeforeResHeaderRender(BeforeResHeaderRenderArgs e)
{
TimeSpan duration = (DateTime) e.DataItem["eventend"] - (DateTime) e.DataItem["eventend"];
string text = duration.ToString(@"d\d");
e.Columns[0].Html = text;
}
VB.NET (GanttController.vb)
Protected Overrides Sub OnBeforeResHeaderRender(ByVal e As BeforeResHeaderRenderArgs)
Dim duration As TimeSpan = CDate(e.DataItem("eventend")).Subtract(CDate(e.DataItem("eventend")))
Dim text As String = duration.ToString("d\d")
e.Columns(0).Html = text
End Sub
Apply a CSS Theme
Apply Windows 8 CSS theme:
C# (Index.cshtml)
@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig
{
BackendUrl = Url.Content("~/Gantt/Backend"),
...
CssOnly = true,
CssClassPrefix = "scheduler_8",
EventHeight = 25
})
VB.NET (Index.vbhtml)
@Html.DayPilotScheduler("dps", New DayPilotSchedulerConfig With
{
.BackendUrl = Url.Content("~/Gantt/Backend"),
...
.CssOnly = True,
.CssClassPrefix = "scheduler_8",
.EventHeight = 25
})
You can create your own theme using the online CSS theme designer.
Add Rows
Normally you can use ViewType = ViewType.Gantt but we want to add one more row for "New Task".
We will use the default ViewType = ViewType.Resources. It is necessary to fill the Resources collection manually.
C# (GanttController.cs)
protected override void OnFinish()
{
Resources.Clear();
Resources.Add("New Task", "NEW");
foreach (DataRow ev in Events)
{
Resource r = new Resource((string)ev["name"], Convert.ToString(ev["id"]));
r.DataItem = ev;
Resources.Add(r);
}
}
VB.NET (GanttController.vb)
Protected Overrides Sub OnFinish()
Resources.Clear()
Resources.Add("New Task", "NEW")
For Each ev As DataRow In Events
Dim r As New Resource(CStr(ev("name")), Convert.ToString(ev("id")))
r.DataItem = ev
Resources.Add(r)
Next ev
End Sub
Adding New Tasks to Gantt Chart
Selecting time cells will activate a modal dialog (DayPilot.Modal). After closing the dialog, control will be passed back to the main page. We will refresh the Gantt chart using commandCallBack() method.
C# (Index.cshtml)
@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig
{
BackendUrl = Url.Content("~/Gantt/Backend"),
...
TimeRangeSelectedHandling = TimeRangeSelectedHandlingType.JavaScript,
TimeRangeSelectedJavaScript = "create(start, end)"
})
VB.NET (Index.vbhtml)
@Html.DayPilotScheduler("dps", New DayPilotSchedulerConfig With
{
.BackendUrl = Url.Content("~/Gantt/Backend"),
...
.TimeRangeSelectedHandling = TimeRangeSelectedHandlingType.JavaScript,
.TimeRangeSelectedJavaScript = "create(start, end)"
})
Modal dialog
<script type="text/javascript">
function create(start, end) {
var modal = new DayPilot.Modal();
modal.closed = function () {
if (this.result == "OK") {
dps.commandCallBack('refresh');
}
dps.clearSelection();
};
modal.showUrl("Event/Create?start=" + start + "&end=" + end);
}
</script>
Refreshing the Gantt chart after adding a new event (Gantt controller).
C# (GanttController.cs)
protected override void OnCommand(CommandArgs e)
{
switch (e.Command)
{
case "refresh":
Update(CallBackUpdateType.Full);
break;
}
}
VB.NET (GanttController.vb)
Protected Overrides Sub OnCommand(ByVal e As CommandArgs)
Select Case e.Command
Case "refresh"
Update(CallBackUpdateType.Full)
End Select
End Sub
Deleting Tasks
Add an active area to every event/task using OnBeforeEventRender() method:
C# (GanttController.cs)
protected override void OnBeforeEventRender(BeforeEventRenderArgs e)
{
e.Areas.Add(new Area().Width(17).Height(16).Right(2).Top(4).CssClass("event_action_delete").JavaScript("dps.commandCallBack('delete', {id:e.value() });"));
}
VB.NET (GanttController.vb)
Protected Overrides Sub OnBeforeEventRender(ByVal e As BeforeEventRenderArgs)
e.Areas.Add((New Area()).Width(17).Height(16).Right(2).Top(4).CssClass("event_action_delete").JavaScript("dps.commandCallBack('delete', {id:e.value() });"))
End Sub
HandlE the "delete" command using OnCommand() method:
C# (GanttController.cs)
protected override void OnCommand(CommandArgs e)
{
switch (e.Command)
{
case "delete":
new EventManager().EventDelete((string) e.Data["id"]);
Update(CallBackUpdateType.Full);
break;
}
}
VB.NET (GanttController.vb)
Protected Overrides Sub OnCommand(ByVal e As CommandArgs)
Select Case e.Command
Case "delete"
CType(New EventManager(), EventManager).EventDelete(CStr(e.Data("id")))
Update(CallBackUpdateType.Full)
End Select
End Sub
Highlight Weekends
Highlight weekend time cells using OnBeforeCellRender method:
C# (GanttController.cs)
protected override void OnBeforeCellRender(BeforeCellRenderArgs e)
{
if (e.Start.DayOfWeek == DayOfWeek.Saturday || e.Start.DayOfWeek == DayOfWeek.Sunday)
{
e.BackgroundColor = "#f3f3f3";
}
}
VB.NET (GanttController.vb)
Protected Overrides Sub OnBeforeCellRender(ByVal e As BeforeCellRenderArgs)
If e.Start.DayOfWeek = DayOfWeek.Saturday OrElse e.Start.DayOfWeek = DayOfWeek.Sunday Then
e.BackgroundColor = "#f3f3f3"
End If
End Sub