This tutorial shows how to display a Gantt chart in ASP.NET MVC using DayPilot Pro ASP.NET MVC scheduler AJAX control.

Includes

  • DayPilot Pro for ASP.NET MVC Trial (7.4.5577)
  • Visual Studio 2010 solution
  • C# project with source code
  • VB.NET project with source code
  • Sample Microsoft SQL Server database (2008)

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. Buy a license.

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 7.9.

See Also

Setup

  1. Include DayPilot.Web.Mvc.dll in the project.
  2. 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),
    CssOnly = true,
    CssClassPrefix = "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),
    .CssOnly = True,
    .CssClassPrefix = "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