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

Includes

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

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),
    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