Search results

Managing Tasks in Blazor Gantt Chart component

22 Jul 2021 / 45 minutes to read

The Blazor Gantt Chart component has options to dynamically insert, delete, and update tasks in a project. The primary key column is necessary to manage the tasks and perform CRUD operations in Gantt Chart. To define the primary key, set the GanttColumn.IsPrimaryKey property to true in the column.

Adding New Tasks

Tasks can be dynamically added to the Gantt Chart project by enabling the GanttEditSettings.AllowAdding property.

Toolbar

A row can be added to the Gantt Chart component from the toolbar while the GanttEditSettings.AllowAdding property is set to true. After clicking the toolbar add icon, you should provide the task information in the add dialog.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<SfGantt DataSource="@TaskCollection" Toolbar="@(new List<string>() { "Add" })" Height="450px" Width="900px">
    <GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress" Child="SubTasks">
    </GanttTaskFields>
    <GanttEditSettings AllowAdding="true"></GanttEditSettings>
</SfGantt>

@code{
    public List<TaskData> TaskCollection { get; set; }
    protected override void OnInitialized()
    {
        this.TaskCollection = GetTaskCollection();
    }

    public class TaskData
    {
        public int TaskId { get; set; }
        public string TaskName { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
        public string Duration { get; set; }
        public int Progress { get; set; }
        public List<TaskData> SubTasks { get; set; }
    }

    public static List <TaskData> GetTaskCollection() {
    List <TaskData> Tasks = new List <TaskData> () {
        new TaskData() {
            TaskId = 1,
            TaskName = "Project initiation",
            StartDate = new DateTime(2019, 04, 02),
            EndDate = new DateTime(2019, 04, 21),
            SubTasks = (new List <TaskData> () {
                new TaskData() {
                    TaskId = 2,
                    TaskName = "Identify Site location",
                    StartDate = new DateTime(2019, 04, 02),
                    Duration = "0",
                    Progress = 30,
                },
                new TaskData() {
                    TaskId = 3,
                    TaskName = "Perform soil test",
                    StartDate = new DateTime(2019, 04, 02),
                    Duration = "4",
                    Progress = 40,
                },
                new TaskData() {
                    TaskId = 4,
                    TaskName = "Soil test approval",
                    StartDate = new DateTime(2019, 04, 02),
                    Duration = "0",
                    Progress = 30
                },
            })
        },
        new TaskData() {
            TaskId = 5,
            TaskName = "Project estimation",
            StartDate = new DateTime(2019, 04, 02),
            EndDate = new DateTime(2019, 04, 21),
            SubTasks = (new List <TaskData> () {
                new TaskData() {
                    TaskId = 6,
                    TaskName = "Develop floor plan for estimation",
                    StartDate = new DateTime(2019, 04, 04),
                    Duration = "3",
                    Progress = 30,
                },
                new TaskData() {
                    TaskId = 7,
                    TaskName = "List materials",
                    StartDate = new DateTime(2019, 04, 04),
                    Duration = "3",
                    Progress = 40
                },
                new TaskData() {
                    TaskId = 8,
                    TaskName = "Estimation approval",
                    StartDate = new DateTime(2019, 04, 04),
                    Duration = "0",
                    Progress = 30,
                }
            })
        }
    };

    return Tasks;
}
}

Alt text

By default, a new row will be added to the top most row in the Gantt Chart component.

Context Menu

A row can also be added above, below or child of the selected row by using context menu support. For this, we need to enable the property EnableContextMenu.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<SfGantt DataSource="@TaskCollection" Height="450px" EnableContextMenu="true" Width="900px" HighlightWeekends="true">
    <GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress"
        Dependency="Predecessor" ParentID="ParentId"></GanttTaskFields>
    <GanttEditSettings AllowAdding="true"></GanttEditSettings>
</SfGantt>

@code{
    public List<TaskData> TaskCollection { get; set; }
    protected override void OnInitialized()
    {
        this.TaskCollection = GetTaskCollection();
    }
    public class TaskData
    {
        public int TaskId { get; set; }
        public string TaskName { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
        public string Duration { get; set; }
        public double Progress { get; set; }
        public string Predecessor { get; set; }
        public int? ParentId { get; set; }
    }

    public static List<TaskData> GetTaskCollection()
    {
        List<TaskData> Tasks = new List<TaskData>() {
            new TaskData() {
                TaskId = 1,
                TaskName = "Project initiation",
                StartDate = new DateTime(2019, 04, 02),
                EndDate = new DateTime(2019, 04, 21)
                },
            new TaskData() {
                TaskId = 2,
                TaskName = "Identify Site location",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
                ParentId = 1
            },
            new TaskData() {
                TaskId = 3,
                TaskName = "Perform soil test",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "4",
                Progress = 40,
                ParentId = 1
            },
            new TaskData() {
                TaskId = 4,
                TaskName = "Soil test approval",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "3",
                Progress = 30,
                Predecessor = "2",
                ParentId = 1
            },
            new TaskData() {
                TaskId = 5,
                TaskName = "Project estimation",
                StartDate = new DateTime(2019, 04, 02),
                EndDate = new DateTime(2019, 04, 21)
            },
            new TaskData() {
                TaskId = 6,
                TaskName = "Develop floor plan for estimation",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 30,
                ParentId = 5
            },
            new TaskData() {
                TaskId = 7,
                TaskName = "List materials",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 40,
                ParentId = 5
            },
            new TaskData() {
                TaskId = 8,
                TaskName = "Estimation approval",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "0",
                Progress = 30,
                Predecessor = "6",
                ParentId = 5
            }
        };
        return Tasks;
    }
}

Using method

You can add rows to the Gantt Chart component dynamically using the AddRecordAsync method and you can define the add position of the default new record by using the RowPosition property. You can also pass the RowIndex as an additional parameter.

  • Top of all the rows.
  • Bottom to all the existing rows.
  • Above the selected row.
  • Below the selected row.
  • As child to the selected row.
Copied to clipboard
@using Syncfusion.Blazor.Gantt
<button @onclick="AddRow">Add Row</button>
<SfGantt @ref="Gantt" DataSource="@TaskCollection" Height="450px" Width="900px">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress" ParentID="ParentId">
</GanttTaskFields>
<GanttEditSettings AllowAdding="true"></GanttEditSettings>
</SfGantt>

@code{
public SfGantt<TaskData> Gantt;
public TaskData record = new TaskData() { TaskId = 9, TaskName = "New Added Record", StartDate = new DateTime(2019, 04, 02), Duration = "3", Progress = 50};

public void AddRow()
{
this.Gantt.AddRecordAsync(record, 2, RowPosition.Below);
}
public List<TaskData> TaskCollection { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
}

public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public int? ParentId { get; set; }
}

public static List <TaskData> GetTaskCollection() {
List <TaskData> Tasks = new List <TaskData> () {

    new TaskData() {
        TaskId = 1,
        TaskName = "Project initiation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21)
    },
    new TaskData() {
        TaskId = 2,
        TaskName = "Identify Site location",
        StartDate = new DateTime(2019, 04, 02),
        Duration = "0",
        Progress = 30,
        ParentId = 1
    },
    new TaskData() {
        TaskId = 3,
        TaskName = "Perform soil test",
        StartDate = new DateTime(2019, 04, 02),
        Duration = "4",
        Progress = 40,
        ParentId = 1
    },
    new TaskData() {
        TaskId = 4,
        TaskName = "Soil test approval",
        StartDate = new DateTime(2019, 04, 02),
        Duration = "0",
        Progress = 30,
        ParentId = 1
    },
    new TaskData() {
        TaskId = 5,
        TaskName = "Project estimation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21)
    },
    new TaskData() {
        TaskId = 6,
        TaskName = "Develop floor plan for estimation",
        StartDate = new DateTime(2019, 04, 04),
        Duration = "3",
        Progress = 30,
        ParentId = 5
    },
    new TaskData() {
        TaskId = 7,
        TaskName = "List materials",
        StartDate = new DateTime(2019, 04, 04),
        Duration = "3",
        Progress = 40,
        ParentId = 5
    },
    new TaskData() {
        TaskId = 8,
        TaskName = "Estimation approval",
        StartDate = new DateTime(2019, 04, 04),
        Duration = "0",
        Progress = 30,
        ParentId = 5
    }
};
return Tasks;
}
}

Alt text

Editing Tasks

The editing feature can be enabled in the Gantt Chart component by enabling the GanttEditSettings.AllowEditing and GanttEditSettings.AllowTaskbarEditing properties.

The following editing options are available to update the tasks in the Gantt chart:

  • Cell
  • Dialog
  • Taskbar

Cell Editing

By setting the edit mode to auto using the GanttEditSettings.Mode property, the tasks can be edited by double-clicking the Tree Grid cells.

The following code example shows you how to enable the cell editing in Gantt Chart component.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<SfGantt DataSource="@TaskCollection" Height="450px" Width="900px">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress" Child="SubTasks">
</GanttTaskFields>
<GanttEditSettings AllowEditing="true" Mode="Syncfusion.Blazor.Gantt.EditMode.Auto"></GanttEditSettings>
</SfGantt>

@code{
public List<TaskData> TaskCollection { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
}

public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public List<TaskData> SubTasks { get; set; }
}

public static List <TaskData> GetTaskCollection() {
List <TaskData> Tasks = new List <TaskData> () {
    new TaskData() {
        TaskId = 1,
        TaskName = "Project initiation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 2,
                TaskName = "Identify Site location",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 3,
                TaskName = "Perform soil test",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "4",
                Progress = 40,
            },
            new TaskData() {
                TaskId = 4,
                TaskName = "Soil test approval",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30
            },
        })
    },
    new TaskData() {
        TaskId = 5,
        TaskName = "Project estimation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 6,
                TaskName = "Develop floor plan for estimation",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 7,
                TaskName = "List materials",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 40
            },
            new TaskData() {
                TaskId = 8,
                TaskName = "Estimation approval",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "0",
                Progress = 30,
            }
        })
    }
};

return Tasks;
}
}

Note: When the edit mode is set to Auto, double-clicking on the Tree Grid side changes, the cells to editable mode. Double-clicking on the chart side opens, the edit dialog for editing the task details.

double click action on Tree Grid side

Alt text

double click action on chart side

Alt text

Dialog Editing

Modify the task details through the edit dialog by setting the GanttEditSettings.Mode as Dialog.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<SfGantt DataSource="@TaskCollection" Height="450px" Width="900px">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress" Child="SubTasks">
</GanttTaskFields>
<GanttEditSettings AllowEditing="true" Mode="Syncfusion.Blazor.Gantt.EditMode.Dialog"></GanttEditSettings>
</SfGantt>

@code{
public List<TaskData> TaskCollection { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
}

public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public List<TaskData> SubTasks { get; set; }
}

public static List <TaskData> GetTaskCollection() {
List <TaskData> Tasks = new List <TaskData> () {
    new TaskData() {
        TaskId = 1,
        TaskName = "Project initiation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 2,
                TaskName = "Identify Site location",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 3,
                TaskName = "Perform soil test",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "4",
                Progress = 40,
            },
            new TaskData() {
                TaskId = 4,
                TaskName = "Soil test approval",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30
            },
        })
    },
    new TaskData() {
        TaskId = 5,
        TaskName = "Project estimation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 6,
                TaskName = "Develop floor plan for estimation",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 7,
                TaskName = "List materials",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 40
            },
            new TaskData() {
                TaskId = 8,
                TaskName = "Estimation approval",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "0",
                Progress = 30,
            }
        })
    }
};

return Tasks;
}
}

Note: In dialog editing mode, the edit dialog appears when the Tree Grid or Gantt chart sides are double-clicked.

Alt text

Sections or Tabs in Dialog

In the Gantt Chart dialog, you can define the required tabs or editing sections using the GanttAddDialogFields and GanttEditDialogFields properties. Every tab is defined using the GanttAddDialogField.Type or GanttEditDialogField.Type property.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<SfGantt DataSource="@TaskCollection" Toolbar="@(new List<string>() { "Add", "Edit" })" Height="450px" Width="700px">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate"
                 Duration="Duration" Progress="Progress" Child="SubTasks" ResourceInfo="ResourceId" Notes="Notes"
                 Dependency="Predecessor">
</GanttTaskFields>
<GanttResourceFields TResources="TaskResources" Name="ResourceName" Id="ResourceId" Resources="@ResourceCollection"></GanttResourceFields>
<GanttEditSettings AllowAdding="true" AllowEditing="true" Mode="Syncfusion.Blazor.Gantt.EditMode.Dialog">
</GanttEditSettings>
<GanttEditDialogFields>
    <GanttEditDialogField Type="GanttDialogFieldType.General" HeaderText="General">
    </GanttEditDialogField>
    <GanttEditDialogField Type="GanttDialogFieldType.Dependency"></GanttEditDialogField>
    <GanttEditDialogField Type="GanttDialogFieldType.Resources"></GanttEditDialogField>
    <GanttEditDialogField Type="GanttDialogFieldType.Notes"></GanttEditDialogField>
</GanttEditDialogFields>
<GanttAddDialogFields>
    <GanttAddDialogField Type="GanttDialogFieldType.General" HeaderText="General Tab"></GanttAddDialogField>
    <GanttAddDialogField Type="GanttDialogFieldType.Dependency"></GanttAddDialogField>
</GanttAddDialogFields>
</SfGantt>

@code{
public List<TaskData> TaskCollection { get; set; }
public List<TaskResources> ResourceCollection { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
    this.ResourceCollection = GetResourceCollections();
}

public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public List<TaskData> SubTasks { get; set; }
    public List<TaskResources> ResourceId { get; set; }
    public string Notes { get; set; }
    public string Predecessor { get; set; }
}
public class TaskResources
{
    public int ResourceId { get; set; }
    public string ResourceName { get; set; }
}

public static List <TaskResources> GetResourceCollections() {
List <TaskResources> Resources = new List <TaskResources> () {
    new TaskResources() {
        ResourceId = 1,
        ResourceName = "Martin Tamer"
    },
    new TaskResources() {
        ResourceId = 2,
        ResourceName = "Rose Fuller"
    },
    new TaskResources() {
        ResourceId = 3,
        ResourceName = "Margaret Buchanan"
    },
    new TaskResources() {
        ResourceId = 4,
        ResourceName = "Fuller King"
    },
    new TaskResources() {
        ResourceId= 5,
        ResourceName= "Davolio Fuller"
    },
};
return Resources;
}

public static List <TaskData> GetTaskCollection() {
List <TaskData> Tasks = new List <TaskData> () {
    new TaskData() {
        TaskId = 1,
        TaskName = "Project initiation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 2,
                TaskName = "Identify Site location",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
                ResourceId = new List<TaskResources>(){ new TaskResources() { ResourceId=1} },
                Notes = "Measure the total property area alloted for construction"
            },
            new TaskData() {
                TaskId = 3,
                TaskName = "Perform soil test",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "4",
                Predecessor = "2",
                ResourceId = new List<TaskResources>(){ new TaskResources() { ResourceId=2}, new TaskResources() { ResourceId=3} },
                Notes = "Obtain an engineered soil test of lot where construction is planned.From an engineer or company specializing in soil testing"

            },
            new TaskData() {
                TaskId = 4,
                TaskName = "Soil test approval",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
                Predecessor = "3"
            },
        })
    },
    new TaskData() {
        TaskId = 5,
        TaskName = "Project estimation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 6,
                TaskName = "Develop floor plan for estimation",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 30,
                Predecessor = "4",
                ResourceId = new List<TaskResources>(){ new TaskResources() { ResourceId=4}},
                Notes = "Develop floor plans and obtain a materials list for estimations"
            },
            new TaskData() {
                TaskId = 7,
                TaskName = "List materials",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Predecessor = "6",
                Notes = ""
            },
            new TaskData() {
                TaskId = 8,
                TaskName = "Estimation approval",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "0",
                Predecessor = "7",
                ResourceId = new List<TaskResources>(){ new TaskResources() { ResourceId=1}, new TaskResources() { ResourceId=5} },
                Notes = ""
            }
        })
    }
};

return Tasks;
}
}

Tabs in Edit Dialog

Alt text

Tabs in Add Dialog

Alt text

Limiting Data Fields in General Tab

In the Gantt Chart dialog, you can make only specific data source fields visible for editing by using the GanttAddDialogFields and GanttEditDialogFields properties. The data fields are defined with GanttEditDialogField.Type and GanttEditDialogField.Fields properties.

Note: You can also define the custom fields in the add/edit dialog General tab using the Fields property.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<SfGantt DataSource="@TaskCollection" Toolbar="@(new List<string>() { "Add", "Edit" })" Height="450px" Width="700px">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate"
                 Duration="Duration" Progress="Progress" Child="SubTasks" ResourceInfo="ResourceId" Notes="Notes"
                 Dependency="Predecessor">
</GanttTaskFields>
<GanttResourceFields TResources="TaskResources" Name="ResourceName" Id="ResourceId" Resources="@ResourceCollections"></GanttResourceFields>
<GanttEditSettings AllowAdding="true" AllowEditing="true" Mode="Syncfusion.Blazor.Gantt.EditMode.Dialog">
</GanttEditSettings>
<GanttColumns>
    <GanttColumn Field="TaskId" Width="100"></GanttColumn>
    <GanttColumn Field="TaskName"></GanttColumn>
    <GanttColumn Field="StartDate"></GanttColumn>
    <GanttColumn Field="Duration"></GanttColumn>
    <GanttColumn Field="Progress"></GanttColumn>
</GanttColumns>
<GanttEditDialogFields>
    <GanttEditDialogField Type="GanttDialogFieldType.General" HeaderText="General"
           Fields="@(new string[]{ "TaskId", "TaskName", "Duration" })"></GanttEditDialogField>
    <GanttEditDialogField Type="GanttDialogFieldType.Notes"></GanttEditDialogField>
</GanttEditDialogFields>
<GanttAddDialogFields>
    <GanttAddDialogField Type="GanttDialogFieldType.General" HeaderText="General Tab"
            Fields="@(new string[]{ "TaskId", "TaskName", "Duration" })"></GanttAddDialogField>
    <GanttAddDialogField Type="GanttDialogFieldType.Dependency"></GanttAddDialogField>
</GanttAddDialogFields>
</SfGantt>

@code{
public List<TaskData> TaskCollection { get; set; }
public List<TaskResources> ResourceCollections { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
    this.ResourceCollections = GetResourceCollections();
}

public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public List<TaskData> SubTasks { get; set; }
    public List<TaskResources> ResourceId { get; set; }
    public string Notes { get; set; }
    public string Predecessor { get; set; }
}
public class TaskResources
{
    public int ResourceId { get; set; }
    public string ResourceName { get; set; }
}

public static List <TaskResources> GetResourceCollections() {
List <TaskResources> Resources = new List <TaskResources> () {
    new TaskResources() {
        ResourceId = 1,
        ResourceName = "Martin Tamer"
    },
    new TaskResources() {
        ResourceId = 2,
        ResourceName = "Rose Fuller"
    },
    new TaskResources() {
        ResourceId = 3,
        ResourceName = "Margaret Buchanan"
    },
    new TaskResources() {
        ResourceId = 4,
        ResourceName = "Fuller King"
    },
    new TaskResources() {
        ResourceId= 5,
        ResourceName= "Davolio Fuller"
    },
};
return Resources;
}

public static List <TaskData> GetTaskCollection() {
List <TaskData> Tasks = new List <TaskData> () {
    new TaskData() {
        TaskId = 1,
        TaskName = "Project initiation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 2,
                TaskName = "Identify Site location",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
                ResourceId = new List<TaskResources>(){ new TaskResources() { ResourceId=1} },
                Notes = "Measure the total property area alloted for construction"
            },
            new TaskData() {
                TaskId = 3,
                TaskName = "Perform soil test",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "4",
                Predecessor = "2",
                ResourceId = new List<TaskResources>(){ new TaskResources() { ResourceId=2}, new TaskResources() { ResourceId=3} },
                Notes = "Obtain an engineered soil test of lot where construction is planned.From an engineer or company specializing in soil testing"
            },
            new TaskData() {
                TaskId = 4,
                TaskName = "Soil test approval",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
                Predecessor = "3"
            },
        })
    },
    new TaskData() {
        TaskId = 5,
        TaskName = "Project estimation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 6,
                TaskName = "Develop floor plan for estimation",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 30,
                Predecessor = "4",
                ResourceId = new List<TaskResources>(){ new TaskResources() { ResourceId=4}},
                Notes = "Develop floor plans and obtain a materials list for estimations"
            },
            new TaskData() {
                TaskId = 7,
                TaskName = "List materials",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Predecessor = "6",
                Notes = ""
            },
            new TaskData() {
                TaskId = 8,
                TaskName = "Estimation approval",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "0",
                Predecessor = "7",
                ResourceId = new List<TaskResources>(){ new TaskResources() { ResourceId=1}, new TaskResources() { ResourceId=5} },
                Notes = ""
            }
        })
    }
};

return Tasks;
}
}

The following screenshot show the output of above code example.

Alt text

Taskbar Editing

Modify the task details through user interaction, such as resizing and dragging the taskbar, by enabling the GanttEditSettings.AllowTaskbarEditing property.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<SfGantt DataSource="@TaskCollection" Height="450px" Width="900px">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress" Child="SubTasks">
</GanttTaskFields>
<GanttEditSettings AllowTaskbarEditing="true"></GanttEditSettings>
</SfGantt>

@code{
public List<TaskData> TaskCollection { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
}

public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public List<TaskData> SubTasks { get; set; }
}

public static List<TaskData> GetTaskCollection()
{
    List<TaskData> Tasks = new List<TaskData>() {
    new TaskData() {
        TaskId = 1,
        TaskName = "Project initiation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 2,
                TaskName = "Identify Site location",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 3,
                TaskName = "Perform soil test",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "4",
                Progress = 40,
            },
            new TaskData() {
                TaskId = 4,
                TaskName = "Soil test approval",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30
            },
        })
    },
    new TaskData() {
        TaskId = 5,
        TaskName = "Project estimation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 6,
                TaskName = "Develop floor plan for estimation",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 7,
                TaskName = "List materials",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 40
            },
            new TaskData() {
                TaskId = 8,
                TaskName = "Estimation approval",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "0",
                Progress = 30,
            }
        })
    }
};

    return Tasks;
}
}

Task Dependencies

In the Gantt Chart component, you can update the dependencies between tasks and link the tasks interactively. The task dependencies can be mapped from the data source using the GanttTaskFields.Dependency property.

You can update the task dependencies using the following ways:

  • Edit dialog: Create or remove the task dependencies using the Dependency tab in the edit dialog.
  • Cell editing: Create or remove the task links using cell editing.

The following code example demonstrates how to enable task dependency editing in the Gantt chart using the EditSettings property.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<SfGantt DataSource="@TaskCollection" Height="450px" Width="700px">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress" Child="SubTasks" Dependency="Predecessor">
</GanttTaskFields>
<GanttEditSettings AllowTaskbarEditing="true" AllowEditing="true" Mode="Syncfusion.Blazor.Gantt.EditMode.Auto"></GanttEditSettings>
</SfGantt>

@code{
public List<TaskData> TaskCollection { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
}

public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public string Predecessor { get; set; }
    public List<TaskData> SubTasks { get; set; }
}

public static List <TaskData> GetTaskCollection() {
List <TaskData> Tasks = new List <TaskData> ();

Tasks.Add(new TaskData() {
    TaskId = 1,
    TaskName = "Project initiation",
    StartDate = new DateTime(2019, 04, 02),
    EndDate = new DateTime(2019, 04, 21),
    SubTasks = (new List <TaskData> () {
        new TaskData() {
            TaskId = 2,
            TaskName = "Identify Site location",
            StartDate = new DateTime(2019, 04, 02),
            Duration = "0",
            Progress = 30,
        },
        new TaskData() {
            TaskId = 3,
            TaskName = "Perform soil test",
            StartDate = new DateTime(2019, 04, 02),
            Duration = "4",
            Progress = 40,
            Predecessor = "2"
        },
        new TaskData() {
            TaskId = 4,
            TaskName = "Soil test approval",
            StartDate = new DateTime(2019, 04, 02),
            Duration = "0",
            Progress = 30,
            Predecessor = "3"
        },
    })

});
Tasks.Add(new TaskData() {
    TaskId = 5,
    TaskName = "Project estimation",
    StartDate = new DateTime(2019, 04, 02),
    EndDate = new DateTime(2019, 04, 21),
    SubTasks = (new List <TaskData> () {
        new TaskData() {
            TaskId = 6,
            TaskName = "Develop floor plan for estimation",
            StartDate = new DateTime(2019, 04, 04),
            Duration = "3",
            Progress = 30,
            Predecessor = "4"
        },
        new TaskData() {
            TaskId = 7,
            TaskName = "List materials",
            StartDate = new DateTime(2019, 04, 04),
            Duration = "3",
            Progress = 40,
            Predecessor = "6"
        },
        new TaskData() {
            TaskId = 8,
            TaskName = "Estimation approval",
            StartDate = new DateTime(2019, 04, 04),
            Duration = "0",
            Progress = 30,
            Predecessor = "7"
        },
    })
});
return Tasks;
}
}

Updating with cell Edit

Alt text

Updating with Dialog

Alt text

Update Task Values using Method

Tasks’ value can be dynamically updated by using the UpdateRecordByIDAsync method. You can call this method on any custom action. The following code example shows how to use this method to update a task.

NOTE: Using the UpdateRecordByIDAsync method, you cannot update the task ID value.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<button @onclick="UpdateRecord">Update Task 3</button>
<SfGantt @ref="Gantt" DataSource="@TaskCollection" Height="450px" Width="900px">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress" Child="SubTasks">
</GanttTaskFields>
<GanttEditSettings AllowEditing="true"></GanttEditSettings>
</SfGantt>

@code{
public SfGantt<TaskData> Gantt;
public void UpdateRecord()
{
    this.Gantt.UpdateRecordByIDAsync(new TaskData() { TaskId = 3, TaskName = "Updated by ID value", Progress = 60});
}
public List<TaskData> TaskCollection { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
}

public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public List<TaskData> SubTasks { get; set; }
}

public static List <TaskData> GetTaskCollection() {
List <TaskData> Tasks = new List <TaskData> () {
    new TaskData() {
        TaskId = 1,
        TaskName = "Project initiation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 2,
                TaskName = "Identify Site location",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 3,
                TaskName = "Perform soil test",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "4",
                Progress = 40,
            },
            new TaskData() {
                TaskId = 4,
                TaskName = "Soil test approval",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30
            },
        })
    },
    new TaskData() {
        TaskId = 5,
        TaskName = "Project estimation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 6,
                TaskName = "Develop floor plan for estimation",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 7,
                TaskName = "List materials",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 40
            },
            new TaskData() {
                TaskId = 8,
                TaskName = "Estimation approval",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "0",
                Progress = 30,
            }
        })
    }
};

return Tasks;
}
}

Alt text

Cell Edit Type and its Params

The GanttColumn.EditType is used to customize the edit type of the particular column. You can set the GanttColumn.EditType based on data type of the column.

Also, you can customize model of the GanttColumn.EditType component through the GanttColumn.EditorSettings.

The following table describes cell edit type component and their corresponding edit params of the column.

Component Example
NumericTextBox @(new { @params = new { format = “n”} })
TextBox -
DropDownList @(new { @params = new { value = “Germany”} })
DatePicker @(new { @params = new { format = “yyyy-MM-dd”} })
DateTimePicker @(new { @params = new { strictMode = true} })
Checkbox @(new { @params = new { checked = true} })
Copied to clipboard
@using Syncfusion.Blazor.Gantt
<SfGantt @ref="Gantt" DataSource="@TaskCollection" Height="450px" Width="900px" Toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" })">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress" Child="SubTasks">
</GanttTaskFields>
<GanttColumns>
    <GanttColumn Field="TaskId" Width="100"></GanttColumn>
    <GanttColumn Field="TaskName" Width="250"></GanttColumn>
    <GanttColumn Field="StartDate" EditorSettings="DateParams" Type="Syncfusion.Blazor.Grids.ColumnType.DateTime" EditType="Syncfusion.Blazor.Grids.EditType.DateTimePickerEdit"></GanttColumn>
    <GanttColumn Field="Duration"></GanttColumn>
    <GanttColumn Field="Progress" EditorSettings="NumericParams" EditType="Syncfusion.Blazor.Grids.EditType.NumericEdit"></GanttColumn>
</GanttColumns>
<GanttEditSettings AllowEditing="true"></GanttEditSettings>
</SfGantt>

@code{
public SfGantt<TaskData> Gantt;
public List<TaskData> TaskCollection { get; set; }
public Syncfusion.Blazor.Grids.NumericEditCellParams NumericParams = new Syncfusion.Blazor.Grids.NumericEditCellParams()
{
    Params = new Syncfusion.Blazor.Inputs.NumericTextBoxModel<object>(){ Format = "N2"  }
};

public Syncfusion.Blazor.Grids.DateEditCellParams DateParams = new Syncfusion.Blazor.Grids.DateEditCellParams()
{
    Params = new Syncfusion.Blazor.Calendars.DatePickerModel(){ Format = "d" }
};
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
}
public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public List<TaskData> SubTasks { get; set; }
}

public static List <TaskData> GetTaskCollection() {
List <TaskData> Tasks = new List <TaskData> () {
    new TaskData() {
        TaskId = 1,
        TaskName = "Project initiation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 2,
                TaskName = "Identify Site location",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 3,
                TaskName = "Perform soil test",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "4",
                Progress = 40,
            },
            new TaskData() {
                TaskId = 4,
                TaskName = "Soil test approval",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
            },
        })
    },
    new TaskData() {
        TaskId = 5,
        TaskName = "Project estimation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 6,
                TaskName = "Develop floor plan for estimation",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 7,
                TaskName = "List materials",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 40,
            },
            new TaskData() {
                TaskId = 8,
                TaskName = "Estimation approval",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "0",
                Progress = 30,
            },
        })
    }
};
return Tasks;
}
}

If edit type is not defined in the column, then it will be considered as the StringEdit type (Textbox component).

Cell Edit Template

The cell edit template is used to add a custom component for a particular column when the column is edited.

The following code example describes, how to define the Edit template for a particular column.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
@using Syncfusion.Blazor.DropDowns;
<SfGantt DataSource="@TaskCollection" Height="450px" Width="700px" Toolbar="@(new List<string>() { "Add", "Cancel", "Edit", "Update", })">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress" ParentID="ParentId">
</GanttTaskFields>
<GanttEditSettings AllowAdding="true" AllowEditing="true"></GanttEditSettings>
<GanttColumns>
    <GanttColumn Field="TaskId" IsPrimaryKey=true></GanttColumn>
    <GanttColumn Field="TaskName">
        <EditTemplate>
            @{
                var task = (context as TaskData);
            }
            <SfDropDownList @ref="dropdown" ID="TaskName" @bind-Value="task.TaskName" TItem="string" TValue="string" DataSource="@DropDownData"></SfDropDownList>
        </EditTemplate>
    </GanttColumn>
    <GanttColumn Field="Duration"></GanttColumn>
    <GanttColumn Field="StartDate"></GanttColumn>
    <GanttColumn Field="Progress"></GanttColumn>
</GanttColumns>
<GanttEditSettings AllowAdding="true" AllowEditing=true AllowTaskbarEditing=true></GanttEditSettings>
<GanttEvents OnActionBegin="ActionBeginHandler" TValue="TaskData"></GanttEvents>
</SfGantt>

@code{
SfDropDownList<string, string> dropdown;

public void ActionBeginHandler(GanttActionEventArgs<TaskData> args)
{
    if (args.RequestType.Equals(Syncfusion.Blazor.Gantt.Action.BeforeSave))
    {
        var data = args.Data as TaskData;
        data.TaskName = dropdown.Value.ToString();
    }
}
public List<TaskData> TaskCollection { get; set; }
public List<string> DropDownData { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
    this.DropDownData = TaskCollection.Select(s => s.TaskName).Distinct().ToList();
}

public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public int? ParentId { get; set; }
}

public static List<TaskData> GetTaskCollection()
{
    List<TaskData> Tasks = new List<TaskData>() {

new TaskData() {
    TaskId = 1,
    TaskName = "Project initiation",
    StartDate = new DateTime(2019, 04, 02),
    EndDate = new DateTime(2019, 04, 21)
},
new TaskData() {
    TaskId = 2,
    TaskName = "Identify Site location",
    StartDate = new DateTime(2019, 04, 02),
    Duration = "4",
    Progress = 30,
    ParentId = 1
},
new TaskData() {
    TaskId = 3,
    TaskName = "Perform soil test",
    StartDate = new DateTime(2019, 04, 02),
    Duration = "4",
    Progress = 40,
    ParentId = 1
},
new TaskData() {
    TaskId = 4,
    TaskName = "Soil test approval",
    StartDate = new DateTime(2019, 04, 02),
    Duration = "4",
    Progress = 30,
    ParentId = 1
},
new TaskData() {
    TaskId = 5,
    TaskName = "Project estimation",
    StartDate = new DateTime(2019, 04, 02),
    EndDate = new DateTime(2019, 04, 21)
},
new TaskData() {
    TaskId = 6,
    TaskName = "Develop floor plan for estimation",
    StartDate = new DateTime(2019, 04, 04),
    Duration = "3",
    Progress = 30,
    ParentId = 5
},
new TaskData() {
    TaskId = 7,
    TaskName = "List materials",
    StartDate = new DateTime(2019, 04, 04),
    Duration = "3",
    Progress = 40,
    ParentId = 5
},
new TaskData() {
    TaskId = 8,
    TaskName = "Estimation approval",
    StartDate = new DateTime(2019, 04, 04),
    Duration = "3",
    Progress = 30,
    ParentId = 5
}
};
    return Tasks;
}
}

Disable Editing for Particular Column

You can disable editing for particular columns, by using the GanttColumn.AllowEditing property.

In the following demo, editing is disabled for the TaskName column.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<SfGantt @ref="Gantt" DataSource="@TaskCollection" Height="450px" Width="900px" Toolbar="@(new List<string>() { "Edit" })">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress" Child="SubTasks">
</GanttTaskFields>
<GanttColumns>
    <GanttColumn Field="TaskId" Width="100"></GanttColumn>
    <GanttColumn Field="TaskName" Width="250" AllowEditing="false"></GanttColumn>
    <GanttColumn Field="StartDate"></GanttColumn>
    <GanttColumn Field="Duration"></GanttColumn>
    <GanttColumn Field="Progress"></GanttColumn>
</GanttColumns>
<GanttEditSettings AllowEditing="true"></GanttEditSettings>
</SfGantt>

@code{
public SfGantt<TaskData> Gantt;
public List<TaskData> TaskCollection { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
}
public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public List<TaskData> SubTasks { get; set; }
}

public static List <TaskData> GetTaskCollection() {
List <TaskData> Tasks = new List <TaskData> () {
    new TaskData() {
        TaskId = 1,
        TaskName = "Project initiation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 2,
                TaskName = "Identify Site location",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 3,
                TaskName = "Perform soil test",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "4",
                Progress = 40,
            },
            new TaskData() {
                TaskId = 4,
                TaskName = "Soil test approval",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
            },
        })
    },
    new TaskData() {
        TaskId = 5,
        TaskName = "Project estimation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 6,
                TaskName = "Develop floor plan for estimation",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 7,
                TaskName = "List materials",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 40,
            },
            new TaskData() {
                TaskId = 8,
                TaskName = "Estimation approval",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "0",
                Progress = 30,
            },
        })
    }
};
return Tasks;
}
}

Deleting Tasks

A task delete option in the Gantt Chart component can be enabled by enabling the GanttEditSettings.AllowDeleting property. Tasks can be deleted by clicking the delete toolbar item or using the DeleteRecordAsync method. You can call this method dynamically on any custom actions like button click. The following code example shows how to enable the delete option in the Gantt Chart component.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<button @onclick="DeleteRow">Delete task 2</button>
<SfGantt @ref="Gantt" DataSource="@TaskCollection" Height="450px" Width="700px">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress" Child="SubTasks">
</GanttTaskFields>
<GanttEditSettings AllowDeleting="true"></GanttEditSettings>
</SfGantt>

@code{
public SfGantt<TaskData> Gantt;
public void DeleteRow()
{
    this.Gantt.DeleteRecordAsync(2);
}
public List<TaskData> TaskCollection { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
}

public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public List<TaskData> SubTasks { get; set; }
}

public static List <TaskData> GetTaskCollection() {
List <TaskData> Tasks = new List <TaskData> () {
    new TaskData() {
        TaskId = 1,
        TaskName = "Project initiation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 2,
                TaskName = "Identify Site location",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 3,
                TaskName = "Perform soil test",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "4",
                Progress = 40,
            },
            new TaskData() {
                TaskId = 4,
                TaskName = "Soil test approval",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30
            },
        })
    },
    new TaskData() {
        TaskId = 5,
        TaskName = "Project estimation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 6,
                TaskName = "Develop floor plan for estimation",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 7,
                TaskName = "List materials",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 40
            },
            new TaskData() {
                TaskId = 8,
                TaskName = "Estimation approval",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "0",
                Progress = 30,
            }
        })
    }
};

return Tasks;
}
}

Alt text

You should set the AllowDeleting value to true to delete the record dynamically.

Delete confirmation message

Delete confirmation message is used to get confirmation from users before deleting a task. This confirmation message can be enabled by setting the GanttEditSettings.ShowDeleteConfirmDialog property to true.

The following code snippet explains how to enable the delete confirmation message in Gantt Chart.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<SfGantt DataSource="@TaskCollection" Height="450px" Width="700px" Toolbar="@(new List<string>() { "Delete" })">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate" Duration="Duration" Progress="Progress" Child="SubTasks">
</GanttTaskFields>
<GanttEditSettings AllowDeleting="true" ShowDeleteConfirmDialog="true"></GanttEditSettings>
</SfGantt>

@code{
public List<TaskData> TaskCollection { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
}

public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public List<TaskData> SubTasks { get; set; }
}

public static List <TaskData> GetTaskCollection() {
List <TaskData> Tasks = new List <TaskData> () {
    new TaskData() {
        TaskId = 1,
        TaskName = "Project initiation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 2,
                TaskName = "Identify Site location",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 3,
                TaskName = "Perform soil test",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "4",
                Progress = 40,
            },
            new TaskData() {
                TaskId = 4,
                TaskName = "Soil test approval",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30
            },
        })
    },
    new TaskData() {
        TaskId = 5,
        TaskName = "Project estimation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 6,
                TaskName = "Develop floor plan for estimation",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 7,
                TaskName = "List materials",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 40
            },
            new TaskData() {
                TaskId = 8,
                TaskName = "Estimation approval",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "0",
                Progress = 30,
            }
        })
    }
};

return Tasks;
}
}

Alt text

Entity FrameWork

You need to follow the below steps to consume data from the Entity Framework in the Gantt Chart component.

Step 1: The first step is to create a SQL database in your Blazor project. Please refer this link to create SQL database.

Step 2: Install the below packages for Entity Framework Support using Nuget or Package manager console using the below command.

Copied to clipboard
Install-Package Microsoft.EntityFrameworkCore.Tools -Version 3.0.0

Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 3.0.0

Step 3: Create a model class GanttDataDetails.cs for the existing database file.

Copied to clipboard
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System;

namespace MyBlazorApp.Data
{

public class GanttDataDetails
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime? Sdate { get; set; }
    public DateTime? Edate { get; set; }
    public string Progress { get; set; }
    public int? ParentId { get; set; }
    public string Duration { get; set; }
    public string ProjectName { get; set; }
    public DateTime? BaselineStartDate { get; set; }
    public DateTime? BaselineEndDate { get; set; }
    public string Predecessor { get; set; }
    public string Notes { get; set; }
    public string TaskType { get; set; }
    public List<TaskResources> ResourceId { get; set; }
    public string ProjectId { get; set; }
    public bool? IsExpand { get; set; }
}
}

Step 4: Create a DB Context class to connect to the Microsoft SQL Server database using the below command in Package Manager Console.

Copied to clipboard
Server=(localdb)\\MSSQLLocalDB;Database=master;Integrated Security=True
Copied to clipboard
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;

namespace GanttEF.Models
{
public partial class masterContext : DbContext
{
    public masterContext()
    {
    }

    public masterContext(DbContextOptions<masterContext> options)
        : base(options)
    {
    }

    public virtual DbSet<Table> Table { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Database=master;Integrated Security=True");
        }
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Table>(entity =>
        {
            entity.Property(e => e.Id).ValueGeneratedNever();

            entity.Property(e => e.Edate).HasColumnType("datetime");

            entity.Property(e => e.Name)
                .HasMaxLength(10)
                .IsFixedLength();

            entity.Property(e => e.Progress)
                .HasMaxLength(10)
                .IsFixedLength();

            entity.Property(e => e.Sdate).HasColumnType("datetime");
        });
        OnModelCreatingPartial(modelBuilder);
    }
    partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
}

Step 5: Update the connection string in the appsettings.json file.

Copied to clipboard
"ConnectionStrings": {
"EmployeeDatabase": "Data Source=(LocalDB)\\\\MSSQLLocalDB;AttachDbFilename=\\\"D:\\client-side-gantt-chart-application-with-entity-framework\\Gantt_wasm_crud_sample1804339720\\Gantt_wasm_crud_sample\\Shared\\App_DataNORTHWND.MDF\\\";Integrated Security=True"
  }

The following sections will give details about the steps needed to be followed when working with server-side and client-side applications individually. You can also find samples attached at the end of each section for server-side applications and client-side applications.

Entity Framework in Server-Side Application

You need to follow the following steps when working with a server-side application.

Custom Adaptor

In Gantt Chart, we can fetch data from the SQL database using Entity Framework Data Model and the update the changes on CRUD action to the server by using DataManager support. To communicate with the remote data, we are using CustomAdaptor of DataManager property to call the server method. You can know more about CustomAdaptor from here. We can populate the datasource in Gantt from the SQL table using Entity Framework using Read method. Please Check the below code snippet to assign the data source to Gantt.

Copied to clipboard
@using GanttEF.Models
@using Syncfusion.Blazor.Gantt
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor


<SfGantt ID="GanttExport" TValue="GanttData" Height="450px" Width="700px"
     Toolbar="@(new List<string>(){ "Add", "Edit", "Update", "Delete", "Cancel", "ExpandAll", "CollapseAll"})">
<SfDataManager AdaptorInstance="@typeof(CustomAdaptor)" Adaptor="Adaptors.CustomAdaptor"></SfDataManager>
<GanttColumns>
    <GanttColumn Field=@nameof(GanttData.Id) Width="100"></GanttColumn>
    <GanttColumn Field=@nameof(GanttData.Name) Width="250"></GanttColumn>
    <GanttColumn Field=@nameof(GanttData.Sdate)></GanttColumn>
    <GanttColumn Field=@nameof(GanttData.Edate)></GanttColumn>
    <GanttColumn Field=@nameof(GanttData.Progress)></GanttColumn>
</GanttColumns>
<GanttEditSettings AllowAdding="true" AllowDeleting="true" AllowEditing="true" AllowTaskbarEditing="true" ShowDeleteConfirmDialog="true" NewRowPosition="RowPosition.Child"></GanttEditSettings>
<GanttTimelineSettings>
    <GanttTopTierSettings Unit="TimelineViewMode.Week" Format="MMM dd, y"></GanttTopTierSettings>
    <GanttBottomTierSettings Unit="TimelineViewMode.Day"></GanttBottomTierSettings>
</GanttTimelineSettings>
<GanttTaskFields Id="Id" Name="Name" StartDate="Sdate" EndDate="Edate" Progress="Progress"
                 ParentID="ParentId"></GanttTaskFields>
</SfGantt>

@code {
// Implementing custom adaptor by extending the DataAdaptor class
public class CustomAdaptor : DataAdaptor
{
    masterContext db = new masterContext();
    // Performs data Read operation
    public override object Read(DataManagerRequest dm, string key = null)
    {
        IEnumerable<GanttData> DataSource = db.GanttData;
        int count = DataSource.Cast<GanttData>().Count();
        return dm.RequiresCounts ? new DataResult() { Result = DataSource, Count = count } : (object)DataSource;
    }
    .../////

}
}

Perform CRUD operation in CustomAdaptor

All the CRUD operations in the Gantt Chart are done through DataManager. The DataManager has an option to bind all the CRUD related data in server-side.

We can do CRUD operations over Gantt data and save the changes into the database. By using BatchUpdate method of DataManager, we can communicate with the controller method to update the data source by CRUD operation. In Gantt Chart, the CRUD actions on a task are dependent on other tasks. For example, if you edit the child record on the chart side, the corresponding parent item also will get affected and predecessor dependency task as well get affected. So, all the CRUD operations in Gantt Chart are considered to be batch editing, where you will get all the affected records as collection.

This server method will be triggered for all the CRUD operations like adding, editing, and deleting actions. We can handle each operation separately inside this method with corresponding data received in this method argument.

The following sample code explains you about, how to implement CRUD operations for the custom bounded data.

Copied to clipboard
@using GanttEF.Models
@using Syncfusion.Blazor.Gantt
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor

<SfGantt ID="GanttExport" TValue="GanttData" Height="450px" Width="700px"
Toolbar="@(new List<string>(){ "Add", "Edit", "Update", "Delete", "Cancel", "ExpandAll", "CollapseAll"})">
<SfDataManager AdaptorInstance="@typeof(CustomAdaptor)" Adaptor="Adaptors.CustomAdaptor"></SfDataManager>
<GanttColumns>
    <GanttColumn Field=@nameof(GanttData.Id) Width="100"></GanttColumn>
    <GanttColumn Field=@nameof(GanttData.Name) Width="250"></GanttColumn>
    <GanttColumn Field=@nameof(GanttData.Sdate)></GanttColumn>
    <GanttColumn Field=@nameof(GanttData.Edate)></GanttColumn>
    <GanttColumn Field=@nameof(GanttData.Progress)></GanttColumn>
</GanttColumns>
<GanttEditSettings AllowAdding="true" AllowDeleting="true" AllowEditing="true" AllowTaskbarEditing="true" ShowDeleteConfirmDialog="true" NewRowPosition="RowPosition.Child"></GanttEditSettings>
<GanttTimelineSettings>
    <GanttTopTierSettings Unit="TimelineViewMode.Week" Format="MMM dd, y"></GanttTopTierSettings>
    <GanttBottomTierSettings Unit="TimelineViewMode.Day"></GanttBottomTierSettings>
</GanttTimelineSettings>
<GanttTaskFields Id="Id" Name="Name" StartDate="Sdate" EndDate="Edate" Progress="Progress"
                 ParentID="ParentId"></GanttTaskFields>
</SfGantt>

@code {
// Implementing custom adaptor by extending the DataAdaptor class
public class CustomAdaptor : DataAdaptor
{
    masterContext db = new masterContext();
    // Performs data Read operation
    public override object Read(DataManagerRequest dm, string key = null)
    {
        IEnumerable<GanttData> DataSource = db.GanttData;
        int count = DataSource.Cast<GanttData>().Count();
        return dm.RequiresCounts ? new DataResult() { Result = DataSource, Count = count } : (object)DataSource;
    }

    // Performs CRUD operation
    public override object BatchUpdate(DataManager dm, object changedRecords, object addedRecords, object deletedRecords, string keyField, string key, int? dropIndex)
    {
        List<GanttData> addRecord = addedRecords as List<GanttData>;
        List<GanttData> changed = changedRecords as List<GanttData>;
        List<GanttData> deleteRecord = deletedRecords as List<GanttData>;
        if (changed != null)
        {
            for (var i = 0; i < changed.Count(); i++)
            {
                var value = changed[i];
                GanttData result = db.GanttData.Where(or => or.Id == value.Id).FirstOrDefault();
                result.Id = value.Id;
                result.Name = value.Name;
                result.Sdate = value.Sdate;
                result.Edate = value.Edate;
                result.Progress = value.Progress;
                db.SaveChanges();
            }
        }
        if (deleteRecord != null)
        {
            for (var i = 0; i < deleteRecord.Count(); i++)
            {
                db.GanttData.Remove(db.GanttData.Where(or => or.Id == deleteRecord[i].Id).FirstOrDefault());
                db.SaveChanges();
            }
        }
        if (addRecord != null)
        {
            for (var i = 0; i < addRecord.Count(); i++)
            {
                db.GanttData.Add(addRecord[i] as GanttData);
                db.SaveChanges();
            }
        }
        return (new { addedRecords = addRecord, changedRecords = changed, deletedRecords = deleteRecord });
    }
}
}

You can find the sample for server-side application using entity framework here.

Entity Framework in Client-Side Application

You need to follow the following steps when working with a client-side application.

Custom Adaptor

In Gantt Chart, we can fetch data from the SQL database using Entity Framework Data Model and the update the changes on CRUD action to the server by using DataManager support. To communicate with the remote data, we are using CustomAdaptor of DataManager property to call the server method. You can know more about CustomAdaptor from here. We can populate the datasource in Gantt from the SQL table using Entity Framework using ReadAsync method. Please Check the below code snippet to assign the data source to Gantt.

Copied to clipboard
@using MyBlazorApp.Shared.DataAccess
@using Syncfusion.Blazor.Gantt
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor
@using MyBlazorApp.Data

<SfGantt ID="GanttExport" TValue="GanttDataDetails" HighlightWeekends="true" RowHeight="75" DurationUnit="DurationUnit.Day"
     Toolbar="@(new List<string>(){ "Add", "Edit", "Update", "Delete", "Cancel", "ExpandAll", "CollapseAll"})">
<SfDataManager Adaptor="Adaptors.CustomAdaptor" DataType="GanttDataDetails">
    <CustomDataAdaptor></CustomDataAdaptor>
</SfDataManager>
<GanttColumns>
    <GanttColumn Field=@nameof(GanttDataDetails.Id) Width="100"></GanttColumn>
    <GanttColumn Field=@nameof(GanttDataDetails.Name) Width="250"></GanttColumn>
    <GanttColumn Field=@nameof(GanttDataDetails.Sdate)></GanttColumn>
    <GanttColumn Field=@nameof(GanttDataDetails.Edate)></GanttColumn>
    <GanttColumn Field=@nameof(GanttDataDetails.Duration)></GanttColumn>
    <GanttColumn Field=@nameof(GanttDataDetails.Progress)></GanttColumn>
    <GanttColumn Field=@nameof(GanttDataDetails.ParentId)></GanttColumn>
</GanttColumns>
<GanttEditSettings AllowAdding="true" AllowDeleting="true" AllowEditing="true" AllowTaskbarEditing="true"></GanttEditSettings>
<GanttTimelineSettings>
    <GanttTopTierSettings Unit="TimelineViewMode.Week" Format="MMM dd, y"></GanttTopTierSettings>
    <GanttBottomTierSettings Unit="TimelineViewMode.Day"></GanttBottomTierSettings>
</GanttTimelineSettings>
<GanttTaskFields Id="Id" Name="Name" StartDate="Sdate" EndDate="Edate" ParentID="ParentId" Progress="Progress" Duration="Duration"></GanttTaskFields>
</SfGantt>

@code {

// Performs data Read operation
public override async Task<object> ReadAsync(DataManagerRequest dm, string key = null)

{
    IEnumerable<object> data = await http.GetJsonAsync<IEnumerable<GanttDataDetails>>("api/GanttDataDetails") as IEnumerable<object>;

    return dm.RequiresCounts ? new DataResult() { Result = data, Count = data.Count() } : (object)data;
}
    .../////
}

Perform CRUD operation in CustomAdaptor

All the CRUD operations in the Gantt Chart are done through DataManager. The DataManager has an option to bind all the CRUD related data in server-side.

The following sample code explains you about, how to implement CRUD operations for the custom bounded data.

Copied to clipboard
@using Newtonsoft.Json
@using MyBlazorApp.Data
@using Syncfusion.Blazor.Gantt
@using Syncfusion.Blazor.Inputs
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor
@using MyBlazorApp.Shared.DataAccess
@inject HttpClient http


@inherits DataAdaptor<GanttDataContext>

@code {


// Performs data Read operation
public override async Task<object> ReadAsync(DataManagerRequest dm, string key = null)

{
    IEnumerable<object> data = await http.GetJsonAsync<IEnumerable<GanttDataDetails>>("api/GanttDataDetails") as IEnumerable<object>;

    return dm.RequiresCounts ? new DataResult() { Result = data, Count = data.Count() } : (object)data;
}

// Performs CRUD operation
public override async Task<object> BatchUpdateAsync(DataManager dm, object changedRecords, object addedRecords, object deletedRecords, string keyField, string key, int? dropIndex)

{

    List<GanttDataDetails> addRecord = addedRecords as List<GanttDataDetails>;
    List<GanttDataDetails> changed = changedRecords as List<GanttDataDetails>;
    List<GanttDataDetails> deleteRecord = deletedRecords as List<GanttDataDetails>;
    if (changed != null)
    {
        for (var i = 0; i < changed.Count(); i++)
        {

            var value = changed[i];
            await http.SendJsonAsync(HttpMethod.Put, "/api/GanttDataDetails/" + changed[i].Id, changed[i] as GanttDataDetails);
        }
    }
    if (deleteRecord != null)
    {
        for (var i = 0; i < deleteRecord.Count(); i++)
        {
            await http.DeleteAsync("api/GanttDataDetails/" + deleteRecord[i].Id);
        }
    }
    if (addRecord != null)
    {


        for (var i = 0; i < addRecord.Count(); i++)
        {
            await http.SendJsonAsync(HttpMethod.Post, "/api/GanttDataDetails", addRecord[i] as GanttDataDetails);
        }
    }
    return (new { addedRecords = addRecord, changedRecords = changed, deletedRecords = deleteRecord });
}
}

You can find the sample for client-side application using entity framework here.

Indent and Outdent

Indent and Outdent of a task are used to update the level of task in the hierarchical order of the task. It can be performed by enabling the GanttEditSettings.AllowEditing property.

Indent - Selected task can be indented to the level of task to the hierarchical order. It can be performed by using in-built context menu or toolbar items. It can also be invoked by using the indent method dynamically on any action like external button click. The following code example shows how to enable indent option in the Gantt chart.

Outdent - Selected task can be outdented to the level of task from the hierarchical order. It can be performed by using in-built context menu or toolbar items. It can also be invoked by using the outdent method dynamically on any action like external button click. The following code example shows how to enable outdent option in the Gantt chart.

Copied to clipboard
@using Syncfusion.Blazor.Gantt
<SfGantt DataSource="@TaskCollection" Toolbar="@(new List<string>() { "Indent", "Outdent" })" Height="450px" Width="900px">
<GanttTaskFields Id="TaskId" Name="TaskName" StartDate="StartDate" EndDate="EndDate"
      Duration="Duration" Progress="Progress" Child="SubTasks"></GanttTaskFields>
<GanttEditSettings AllowEditing="true" AllowAdding="true" AllowDeleting="true">
</GanttEditSettings>
</SfGantt>

@code{
public List<TaskData> TaskCollection { get; set; }
protected override void OnInitialized()
{
    this.TaskCollection = GetTaskCollection();
}

public class TaskData
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Duration { get; set; }
    public int Progress { get; set; }
    public List<TaskData> SubTasks { get; set; }
}

public static List <TaskData> GetTaskCollection() {
List <TaskData> Tasks = new List <TaskData> () {
    new TaskData() {
        TaskId = 1,
        TaskName = "Project initiation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 2,
                TaskName = "Identify Site location",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 3,
                TaskName = "Perform soil test",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "4",
                Progress = 40,
            },
            new TaskData() {
                TaskId = 4,
                TaskName = "Soil test approval",
                StartDate = new DateTime(2019, 04, 02),
                Duration = "0",
                Progress = 30
            },
        })
    },
    new TaskData() {
        TaskId = 5,
        TaskName = "Project estimation",
        StartDate = new DateTime(2019, 04, 02),
        EndDate = new DateTime(2019, 04, 21),
        SubTasks = (new List <TaskData> () {
            new TaskData() {
                TaskId = 6,
                TaskName = "Develop floor plan for estimation",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 30,
            },
            new TaskData() {
                TaskId = 7,
                TaskName = "List materials",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "3",
                Progress = 40
            },
            new TaskData() {
                TaskId = 8,
                TaskName = "Estimation approval",
                StartDate = new DateTime(2019, 04, 04),
                Duration = "0",
                Progress = 30,
            }
        })
    }
};
return Tasks;
}
}

Troubleshoot: Editing works only when primary key column is defined

Editing feature requires a primary key column for CRUD operations. While defining columns in Gantt using the GanttColumns property, it is mandatory that any one of the columns, must be a primary column. By default, the Id column will be the primary key column. If Id column is not defined, we need to enable IsPrimaryKey for any one of the columns defined in the GanttColumns property.