TaskUpdate#
An edit to one existing task of a live project. It goes in the Update list of SchedulingChanges.Tasks, which Project.Apply and Project.Preview take. Create it with new TaskUpdate(id) and set the fields to change in an object initializer.
Declaration#
public sealed class TaskUpdate : IDeepCloneable<TaskUpdate>
Constructors#
TaskUpdate(Id)#
public TaskUpdate(Id id)
Creates an update for the task with the given id. Every other property is Patch<T>.Missing, so the update changes nothing until a property is set.
| Name | Type | Description |
|---|---|---|
id |
Id |
Id of the task to edit. A string, int or double converts implicitly. |
Properties#
Every property except Id is a Patch<T>. Missing (the default) keeps the stored value, a value sets it, and Null clears it. The On Null column shows what Null leaves behind. For the meaning of each value, see the property of the same name on TaskData.
A plain value converts implicitly to a Patch<T>, so Duration = 3.0 works. An Id property needs Patch<Id>.Of(...) when the value is a string or a number, because C# doesn't chain the two implicit conversions.
| Property | Type | On Null |
Description |
|---|---|---|---|
Id |
Id |
required | Id of the task to edit. |
Parent |
Patch<Id> |
root level | Moves the task under another parent. A value equal to SchedulingConfig.RootId is read as Null. |
StartDate |
Patch<Moment> |
null |
New start, for example after a drag. |
EndDate |
Patch<Moment> |
null |
New end. |
Duration |
Patch<double> |
null |
New working time in the task's DurationUnit, for example after a resize. |
ConstraintType |
Patch<ConstraintType> |
null |
New scheduling constraint. |
ConstraintDate |
Patch<Moment> |
null |
New constraint date. |
AutoScheduling |
Patch<bool> |
true |
false makes the task fixed. |
Unscheduled |
Patch<bool> |
false |
true takes the task out of the plan. |
Progress |
Patch<double> |
0.0 |
New completed fraction. |
CalendarId |
Patch<Id> |
null |
New working calendar. |
Priority |
Patch<ushort> |
500 |
New leveling priority. |
LevelingDelay |
Patch<double> |
0.0 |
New leveling delay, as elapsed time in the task's DurationUnit. |
Pauses |
Patch<List<Pause>> |
empty | Replaces the whole pause list. The task gets its own copy of the list. |
Dates after an update#
An update starts from the task's current scheduled start, end and duration. On a leaf task (TaskType.Task), the properties set in the update decide which of the three is kept and which is derived again:
| Set in the update | Kept | Derived again |
|---|---|---|
StartDate, no EndDate |
start, duration | end |
EndDate only |
end, start | duration |
Duration, no EndDate |
start, duration | end |
StartDate + EndDate, no Duration |
start, end | duration |
CalendarId, or Parent under CalendarMode.TaskInherited, no date property |
start, duration | end |
Pauses or LevelingDelay, no date property |
start, duration | end |
- A
LevelingDelayupdate with neitherStartDatenorEndDatealso moves the stored dates by the change in delay (elapsed time) and snaps them onto working time. - When a task works on several calendars in a project with
ScheduleFromEndon, aPausesorLevelingDelayupdate without dates keeps the end and derives the start instead. - Under
CalendarMode.TaskInherited, aCalendarIdorParentupdate also re-derives the end of each descendant leaf task that has noCalendarIdof its own. Its start and duration stay. - An explicit start on non-working time stays unsnapped when the task has no predecessor.
To write a result entry back as an update, see Mutation.
Methods#
DeepClone#
public TaskUpdate DeepClone()
Returns a copy that shares no list with this update, including the Pauses value.
Returns: a new TaskUpdate with the same values.
ToString#
public override string ToString()
Returns a debug dump of the fields, e.g. TaskUpdate { Id: a, Parent: Missing, StartDate: Missing, … }.
Errors#
An update is rejected as a single operation, at path tasks.update[i]. Project.Apply and Project.Preview describe how a rejection is reported.
| Message | When it occurs |
|---|---|
unknown task id |
No task has Id. |
| a validation message | The edited task breaks a TaskData rule or a ProjectData rule, for example an unknown CalendarId or Parent. |
Example#
Move a task to a new start and make it one day longer:
using Plen;
var monday = Moment.FromYmdHm(2026, 4, 6, 8, 0) ?? throw new InvalidOperationException("invalid date");
var wednesday = Moment.FromYmdHm(2026, 4, 8, 8, 0) ?? throw new InvalidOperationException("invalid date");
var data = new ProjectData
{
Tasks = [new TaskData("design") { StartDate = monday, Duration = 2.0 }],
};
var project = new Project();
project.Solve(data, new SolveOptions());
var changes = new SchedulingChanges();
changes.Tasks.Update.Add(new TaskUpdate("design") { StartDate = wednesday, Duration = 3.0 });
var report = project.Apply(changes);
if (report.Rejected.Count == 0)
{
var result = project.Solve(null, new SolveOptions());
foreach (var task in result.Updates)
{
Console.WriteLine($"{task.Id}: {task.StartDate} - {task.EndDate}");
}
}
Related#
TaskData- the record being editedSchedulingChanges- the change set that carries the updatePatch<T>- the three-state field typeMutation- a result entry to write back- Editing a project - the full edit cycle