VARCHART XGantt is a powerful Gantt control (.NET and ActiveX edition) enabling you to create intelligent Gantt charts with little effort. Recently, one of our customers contacted us having a quite complex problem which our support could help to solve. As I’m sure that other developers working with VARCHART XGantt will also be interested in the approach we came up with I decided to give you a brief outline of the problem and its solution .
The approach involves interactively swapping tasks via the table and, as a consequence, adjusting the order in which they have to be processed.
Initial Situation
The customer has developed a graphical planning board for managing his machinery with VARCHART XGantt .NET edition. On the machines the tasks run in sequence and without buffer times. In the table area of the planning table, the tasks are listed correspondingly one below the other ordered by start date. This is displayed in the Gantt area as „descending stair“.
Requirement
The customer wanted to be able to change the tasks‘ order within a machine by drag and drop and in the table area only. Technically, this problem had to be realized by making a task that has been moved up in the table e.g., the predecessor (in time) of the task above which it has been placed. For this, the processiong order of the tasks needs to be changed accordingly. If, e.g., task 2 and task3 have to swapped, this should look like shown below:
Before moving:
After moving:
The Solution
Moving a node interactively in VARCHART XGantt triggers the events VcNodeModifying and VcNodeModifiedEx.
VcNodemodifying first checks whether the task has been moved to another group because, according to specification, this should not be allowed. To achieve this it needs to be checked, whether after moving the task the content of its Machine data field (the grouping field) has changed or not. If the content has changed, the ReturnStatus will be set to vcRetStatFalse , thus undoing the moving. In this case, the event VcNodeModifiedEx will not appear.
private void vcGantt1_VcNodeModifying(object sender, VcNodeModifyingEventArgs e)
{
//Make sure that a task cannot be moved to another machine
string oldGroupName = e.OldNode.get_DataField(eMainData.Machine).ToString();
string newGroupName = e.Node.get_DataField(eMainData.Machine).ToString();
e.ReturnStatus = oldGroupName == newGroupName ?
VcReturnStatus.vcRetStatDefault : VcReturnStatus.vcRetStatFalse;
}
If moving the task was allowed (the task was moved within its group) the tasks have to be rescheduled. This is done in the VcNodeModifiedEx event by searching the earliest start date of all tasks of the group. Then you run over all tasks of the group again and recalculate their start and end dates, beginning with the earliest start date and taking into account the corresponding machine calendar. In the VcNodeCollection nodesInGroup (see code!) the nodes are listed in the order that is displayed in the table.
private void vcGantt1_VcNodeModifiedEx(object sender, VcNodeModifiedExEventArgs e)
{
DateTime minStartDate = DateTime.MaxValue;
DateTime startDate;
DateTime endDate;
VcCalendar cal =
vcGantt1.CalendarCollection.CalendarByName(e.Node.get_DataField(eMainData.Machine).ToString());
VcNodeCollection nodesInGroup = e.Node.SuperGroup.NodeCollection;
//Mark the moved node as "moved"
e.Node.set_DataField(eMainData._Moved, "1");
e.Node.Update();
//Search for the earliest start date of the nodes in the group
foreach (VcNode node in nodesInGroup)
{
startDate = Convert.ToDateTime(node.get_DataField(eMainData.Start));
minStartDate = (startDate < minStartDate ? startDate : minStartDate);
}
startDate = minStartDate;
//Reposition the tasks on the machine so that they follow each other
//without gaps or overlaps.
vcGantt1.SuspendUpdate(true);
foreach (VcNode node in nodesInGroup)
{
endDate = cal.AddDuration(startDate, Convert.ToInt32(node.get_DataField(eMainData.Duration)));
node.set_DataField(eMainData.Start, startDate);
node.set_DataField(eMainData.End, endDate);
node.Update();
startDate = (cal.IsWorktime(endDate) ? endDate : cal.GetStartOfNextWorktime(endDate));
}
vcGantt1.SuspendUpdate(false);
}
After recalculating the dates, the tasks are displayed as descending stair again.
Want to learn more tips & tricks?
Here are some more blog post, I would like to recommend:
From Awful to Awesome Progress Visualization in Gantt Charts
Three Steps to Add a Comfortable Sorting Option to Grouped Gantt Charts
Do you know that our VARCHART XGantt control has a live-update function? This means that if you move a task you immediately see the consequences for all other related tasks during the interaction. Download our free whitepaper for best practices.