Task Dependencies
- 9 minutes to read
The Gantt control can display task dependencies of the following types:
FinishToStart — a successor should start when its predecessor finishes.
FinishToFinish — a successor should finish when its predecessor finishes.
StartToFinish — a successor should finish when its predecessor starts.
StartToStart — a successor should start when its predecessor starts.
How to Specify Dependencies
To specify dependencies, use data source fields. If you only need finish-to-start dependencies, you can use the same data source for tasks and dependencies. If you need all dependency types, use a separate data source for dependencies.
Finish-to-Start Dependency Type
If you only need the finish-to-start dependency type, use the GanttControl.DataSource property to specify the data source that contains tasks and dependencies. A data record represents a task and contains information about its caption, start and finish dates, duration, and predecessors. The GanttControl.ChartMappings property provides access to the PredecessorsFieldName property to specify a task’s predecessors.
The code below shows how to specify tasks and dependencies.
ganttControl1.TreeListMappings.KeyFieldName = "ID";
ganttControl1.TreeListMappings.ParentFieldName = "ParentID";
ganttControl1.ChartMappings.TextFieldName = "Text";
ganttControl1.ChartMappings.StartDateFieldName = "StartDate";
ganttControl1.ChartMappings.FinishDateFieldName = "FinishDate";
ganttControl1.ChartMappings.PredecessorsFieldName = "Predecessors";
ganttControl1.DataSource = GetTasks();
DataTable GetTasks() {
DataTable table = new DataTable();
DataColumn id = new DataColumn("ID", typeof(int));
DataColumn parentId = new DataColumn("ParentID", typeof(int));
DataColumn text = new DataColumn("Text", typeof(string));
DataColumn start = new DataColumn("StartDate", typeof(DateTime));
DataColumn finish = new DataColumn("FinishDate", typeof(DateTime));
DataColumn predecessors = new DataColumn("Predecessors", typeof(string));
table.Columns.AddRange(new DataColumn[] { id, parentId, text, start, finish, predecessors });
table.Rows.Add(new object[] { 1, 0, "Task 1", DateTime.Now, DateTime.Now.AddDays(1), null });
table.Rows.Add(new object[] { 2, 0, "Task 2", DateTime.Now.AddDays(1), DateTime.Now.AddDays(2), 1 });
table.Rows.Add(new object[] { 3, 0, "Task 3", DateTime.Now.AddDays(2), DateTime.Now.AddDays(3), "1, 2"});
return table;
}
See Bind to Data Source for more information about data source mappings.
All Dependency Types
If you need all dependency types, use the GanttControl.DependencySource property to specify the data source that contains dependencies. A data record represents a dependency and specifies its type, predecessor, successor, etc. The GanttControl.DependencyMappings property provides access to the following properties:
- PredecessorFieldName — specifies a predecessor task’s key.
- SuccessorFieldName — specifies a successor task’s key.
- TypeFieldName — specifies the dependency type (finish-to-start, finish-to-finish, etc.).
- LagFieldName — specifies the time lag between the successor and the predecessor. If a user moves a predecessor, the control automatically reschedules all its successors with respect to the time lag.
Note
If you use these properties and the GanttControl.DependencySource property to specify dependencies, dependencies specified with the PredecessorsFieldName and GanttControl.DataSource properties are not in effect.
The code below shows how to specify tasks and dependencies.
using DevExpress.XtraGantt;
ganttControl1.TreeListMappings.KeyFieldName = "ID";
ganttControl1.TreeListMappings.ParentFieldName = "ParentID";
ganttControl1.ChartMappings.TextFieldName = "Text";
ganttControl1.ChartMappings.StartDateFieldName = "StartDate";
ganttControl1.ChartMappings.FinishDateFieldName = "FinishDate";
ganttControl1.DataSource = GetTasks();
ganttControl1.DependencyMappings.PredecessorFieldName = "PredecessorID";
ganttControl1.DependencyMappings.SuccessorFieldName = "SuccessorID";
ganttControl1.DependencyMappings.TypeFieldName = "DependencyType";
ganttControl1.DependencyMappings.LagFieldName = "TimeLag";
ganttControl1.DependencySource = GetDependencies();
DataTable GetTasks() {
DataTable table = new DataTable();
DataColumn id = new DataColumn("ID", typeof(int));
DataColumn parentId = new DataColumn("ParentID", typeof(int));
DataColumn text = new DataColumn("Text", typeof(string));
DataColumn start = new DataColumn("StartDate", typeof(DateTime));
DataColumn finish = new DataColumn("FinishDate", typeof(DateTime));
table.Columns.AddRange(new DataColumn[] { id, parentId, text, start, finish });
table.Rows.Add(new object[] { 1, 0, "Task 1", DateTime.Now, DateTime.Now.AddDays(1) });
table.Rows.Add(new object[] { 2, 0, "Task 2", DateTime.Now.AddDays(1), DateTime.Now.AddDays(2) });
table.Rows.Add(new object[] { 3, 0, "Task 3", DateTime.Now.AddDays(2), DateTime.Now.AddDays(3) });
return table;
}
DataTable GetDependencies() {
DataTable table = new DataTable();
DataColumn predecessor = new DataColumn("PredecessorID", typeof(int));
DataColumn successor = new DataColumn("SuccessorID", typeof(int));
DataColumn dependencyType = new DataColumn("DependencyType", typeof(DevExpress.XtraGantt.DependencyType));
DataColumn lag = new DataColumn("TimeLag", typeof(TimeSpan));
table.Columns.AddRange(new DataColumn[] { predecessor, successor, dependencyType, lag });
table.Rows.Add(new object[] { 1, 2, DependencyType.StartToFinish, new TimeSpan(12, 0, 0) });
table.Rows.Add(new object[] { 2, 3, DependencyType.StartToStart, null });
return table;
}
Modify Dependencies
If the AllowModifyDependencies option is enabled, users can modify dependencies. See Interactive Editing for more information.
Obtain Dependencies in Code
Use the methods below to obtain a task’s predecessors. You can use a GanttControlNode object or Id property value to specify the task.
GetPredecessorNodes(GanttControlNode), GetPredecessorNodes(Int32), and GetPredecessorNodes() - return an IEnumerable<T> collection of GanttControlNode objects that specify a task’s predecessors.
If the control is bound to a data source, these methods are not in effect if you call them before the control is displayed onscreen because nodes are not created yet. You can call the ForceInitialize() method to force node creation.
GetPredecessors(GanttControlNode), GetPredecessors(Int32), and GetPredecessors() - return keys (see KeyFieldName) of a task’s predecessors.
If you use the DependencySource property to specify dependencies, the returned value is a List<T> of keys as they are specified in the data source (see PredecessorFieldName).
If you use the DataSource property to specify dependencies, the returned value is an object as it is specified in the data source (see PredecessorsFieldName).
Use the methods below to obtain a task’s successors. You can use a GanttControlNode object or Id property value to specify the task.
GetSuccessorNodes(GanttControlNode), GetSuccessorNodes(Int32), and GetSuccessorNodes() - return an IEnumerable<T> collection of GanttControlNode objects that specify a task’s successors.
If the control is bound to a data source, these methods are not in effect if you call them before the control is displayed onscreen because nodes are not created yet. You can call the ForceInitialize() method to force node creation.
GetSuccessors(GanttControlNode), GetSuccessors(Int32), and GetSuccessors() - return keys (see KeyFieldName) of a task’s successors.
If you use the DependencySource property to specify dependencies, the returned value is a List<T> of keys as they are specified in the data source (see SuccessorFieldName).
If you use the DataSource property to specify dependencies, you cannot get successors because this data source stores predecessors only.
Example
The example below shows how to get a task’s predecessors and successors. You can use the FindNodeByFieldValue(String, Object) method to retrieve a GanttControlNode object by the content in a specific field.
using DevExpress.XtraGantt;
using System.Collections.Generic;
// The following methods return nodes that specify a task's predecessors and successors.
IEnumerable<GanttControlNode> predecessorNodes =
ganttControl1.GetPredecessorNodes(0);
IEnumerable<GanttControlNode> predecessorNodes1 =
ganttControl1.GetPredecessorNodes(ganttControl1.FindNodeByFieldValue("Text", "Task 2") as GanttControlNode);
IEnumerable<GanttControlNode> predecessorNodes2 =
(ganttControl1.FindNodeByFieldValue("Text", "Task 3") as GanttControlNode).GetPredecessorNodes();
IEnumerable<GanttControlNode> successorNodes =
ganttControl1.GetSuccessorNodes(0);
IEnumerable<GanttControlNode> successorNodes1 =
ganttControl1.GetSuccessorNodes(ganttControl1.FindNodeByFieldValue("Text", "Task 2") as GanttControlNode);
IEnumerable<GanttControlNode> successorNodes2 =
(ganttControl1.FindNodeByFieldValue("Text", "Task 3") as GanttControlNode).GetSuccessorNodes();
// The following methods return keys
// (as they are specified in the data source) of a task's predecessors and successors.
// If you use the DependencySource property to specify dependencies,
// the returned value is of List<object> type. Items in the collection are keys of the corresponding type.
List<object> predecessorKeyList =
ganttControl1.GetPredecessors(0) as List<object>;
List<object> predecessorsKeyList1 =
ganttControl1.GetPredecessors(ganttControl1.FindNodeByFieldValue("Text", "Task 2") as GanttControlNode) as List<object>;
List<object> predecessorsKeyList2 =
(ganttControl1.FindNodeByFieldValue("Text", "Task 3") as GanttControlNode).GetPredecessors() as List<object>;
List<object> successorKeyList =
ganttControl1.GetSuccessors(0) as List<object>;
List<object> successorsKeyList1 =
ganttControl1.GetSuccessors(ganttControl1.FindNodeByFieldValue("Text", "Task 2") as GanttControlNode) as List<object>;
List<object> successorsKeyList2 =
(ganttControl1.FindNodeByFieldValue("Text", "Task 3") as GanttControlNode).GetSuccessors() as List<object>;
// If you use the DataSource property to specify dependencies,
// the returned value is of the same type as in the data source.
// Note that you cannot get successors in this case
// since the data source stores predecessors only.
var predecessorKeys =
ganttControl1.GetPredecessors(0);
var predecessorsKeys1 =
ganttControl1.GetPredecessors(ganttControl1.FindNodeByFieldValue("Text", "Task 2") as GanttControlNode);
var predecessorsKeys2 =
(ganttControl1.FindNodeByFieldValue("Text", "Task 3") as GanttControlNode).GetPredecessors();