Thursday, 28 March 2013

Gantt Chart Tutorial (ASP.NET, SQL Server, C#, VB.NET)


Gantt Chart Tutorial (ASP.NET, SQL Server, C#, VB.NET)

How to create a Gantt Chart application in ASP.NET.

Downloads

Sample Project

The sample project includes:

Online Demo

Requirements

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

Features

This tutorial shows how to create a Gantt Chart ASP.NET application using DayPilot Scheduler control.
  • Displays one task per row
  • Drag&drop task creating using a special row (New Task)
  • Drag&drop task moving (restricted to its own row)
  • Drag&drop task resizing
  • Context menu
  • Fast callout with task details (bubble)
  • Task detail editing using a modal popup
  • Automatic row header width adjustment

1. Creating a Gantt Chart

DayPilot Scheduler can be switched to a special Gantt mode using ViewType="Gantt". This Gantt mode automatically creates one row for each resource (using the event/task id as the resource id).
gantt-chart-asp-net.png
        <DayPilot:DayPilotScheduler
            ID="DayPilotScheduler1" 
            runat="server" 
            DataEndField="TaskEnd"
            DataStartField="TaskStart" 
            DataTextField="TaskName" 
            DataValueField="TaskId" 
            DataResourceField="TaskId"

            ViewType="Gantt"
        />
We want to add a special first row that will be used for adding new tasks so we have to create the rows manually:
gantt-chart-asp-net-new-task.png
The following method creates the rows from tasks.
C#
    private void LoadResources()
    {
        DataTable locations = new DataManager().GetTasks();
        DayPilotScheduler1.Resources.Clear();
        DayPilotScheduler1.Resources.Add("New Task", "NEW");
        foreach (DataRow dr in locations.Rows)
        {
            DayPilotScheduler1.Resources.Add((string)dr["TaskName"], Convert.ToString(dr["TaskId"]));
        }
    }
VB.NET
Private Sub LoadResources()
  Dim locations As DataTable = (New DataManager()).GetTasks()
  DayPilotScheduler1.Resources.Clear()
  DayPilotScheduler1.Resources.Add("New Task", "NEW")
  For Each dr As DataRow In locations.Rows
    DayPilotScheduler1.Resources.Add(CStr(dr("TaskName")), Convert.ToString(dr("TaskId")))
  Next dr
End Sub

2. Adding Tasks to Gantt Chart

The following properties enable drag&drop task creating:
<DayPilot:DayPilotScheduler
  ...
  TimeRangeSelectedJavaScript="timeRangeSelected(start, end, resource);"
  TimeRangeSelectedHandling="JavaScript"
  ...
/>
The timeRangeSelected() method uses a modal dialog to display a separate New.aspx page that asks for task details.
gantt-chart-new-task.png
JavaScript
function timeRangeSelected(start, end, resource) {
    if (resource !== 'NEW') {
        dp.clearSelection();
        dp.message("Use the 'New Task' row");
        return;
    }

    var modal = dialog();
    var url = "New.aspx?start=" + start.toStringSortable() + "&end=" + end.toStringSortable();
    modal.showUrl(url);
}

function dialog() {
    var modal = new DayPilot.Modal();
    modal.top = 60;
    modal.width = 250;
    modal.height = 150;
    modal.opacity = 70;
    modal.border = "10px solid #d0d0d0";
    modal.closed = function () {
        if (this.result == "OK") {
            dp.commandCallBack('refresh');
        }
        dp.clearSelection();
    };
    return modal;
}

3. Task Moving and Resizing

gantt-chart-asp-net-task-moving.png
Task moving and resizing is enabled using the following properties:
<DayPilot:DayPilotScheduler
  ...
  EventResizeHandling="CallBack" 
  OnEventResize="DayPilotCalendar1_EventResize"
  EventMoveHandling="CallBack" 
  OnEventMove="DayPilotCalendar1_EventMove"
  ...
/>
The user actions (moving, resizing) will invoke server-side EventMove and EventResize handlers.
C#
protected void DayPilotCalendar1_EventResize(object sender, EventResizeEventArgs e)
{
  int id = Convert.ToInt32(e.Value);
  new DataManager().MoveTask(id, e.NewStart, e.NewEnd);
  LoadResources(); // update order
  UpdateScheduler();
}

protected void DayPilotCalendar1_EventMove(object sender, EventMoveEventArgs e)
{
  int id = Convert.ToInt32(e.Value);
  new DataManager().MoveTask(id, e.NewStart, e.NewEnd);
  LoadResources(); // update order
  UpdateScheduler();
}
VB.NET
Protected Sub DayPilotCalendar1_EventResize(ByVal sender As Object, ByVal e As EventResizeEventArgs)
  Dim id As Integer = If(e.Recurrent, Convert.ToInt32(e.RecurrentMasterId), Convert.ToInt32(e.Value))
  CType(New DataManager(), DataManager).MoveTask(id, e.NewStart, e.NewEnd)
  LoadResources() ' update order
  UpdateScheduler()
End Sub

Protected Sub DayPilotCalendar1_EventMove(ByVal sender As Object, ByVal e As EventMoveEventArgs)
  Dim id As Integer = If(e.Recurrent, Convert.ToInt32(e.RecurrentMasterId), Convert.ToInt32(e.Value))
  CType(New DataManager(), DataManager).MoveTask(id, e.NewStart, e.NewEnd)
  LoadResources() ' update order
  UpdateScheduler()
End Sub
We will forbid moving the task to other rows using BeforeEventRender:
C#
protected void DayPilotCalendar1_BeforeEventRender(object sender, BeforeEventRenderEventArgs e)
{
  e.EventMoveVerticalEnabled = false;
}
VB.NET
Protected Sub DayPilotCalendar1_BeforeEventRender(ByVal sender As Object, ByVal e As BeforeEventRenderEventArgs)
  e.EventMoveVerticalEnabled = False
End Sub

4. Displaying Gantt Chart Task Details (Callout)

The callout will be displayed using DayPilot Bubble control:
gantt-chart-asp-net-task-detail.png
<DayPilot:DayPilotBubble 
  ID="BubbleEvent" 
  runat="server" 
  CssOnly="true" 
  CssClassPrefix="bubble_default"
  ShowAfter="100"
>
</DayPilot:DayPilotBubble>
By default, the bubble calls DayPilotBubble.RenderEventBubble event to get its content.
We will set the bubble content in advance using DayPilotScheduler.BeforeEventRender event. This way, it will not have to contact the server and the callout will be displayed faster.
C#
protected void DayPilotCalendar1_BeforeEventRender(object sender, BeforeEventRenderEventArgs e)
{
  e.EventMoveVerticalEnabled = false;
  e.StaticBubbleHTML = String.Format("<b>{0}</b><br/>Start: {1}<br/>End: {2}", e.Text, e.Start, e.End);
}
VB.NET
Protected Sub DayPilotCalendar1_BeforeEventRender(ByVal sender As Object, ByVal e As BeforeEventRenderEventArgs)
  e.EventMoveVerticalEnabled = False
  e.StaticBubbleHTML = String.Format("<b>{0}</b><br/>Start: {1}<br/>End: {2}", e.Text, e.Start, e.End)
End Sub

5. Automatic Row Header Width Adjustment

gantt-chart-row-header-width.png
The row header width can be set using RowHeaderWidth property (in pixels):
RowHeaderWidth="120"
It can be adjusted automatically to fit the longest header text using RowHeaderWidthAutoFit property:
RowHeaderWidthAutoFit="true"

No comments:

Post a Comment