[Canonical page](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/task-update/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# TaskUpdate

An edit to one existing task of a live project. It goes in the `Update` list of [`SchedulingChanges.Tasks`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/scheduling-changes.md>), which [`Project.Apply`](<https://docs.dhtmlx.com/planning-engine/net/api/project-apply.md>) and [`Project.Preview`](<https://docs.dhtmlx.com/planning-engine/net/api/project-preview.md>) take. Create it with `new TaskUpdate(id)` and set the fields to change in an object initializer.

## Declaration

```csharp
public sealed class TaskUpdate : IDeepCloneable<TaskUpdate>
```

## Constructors

### TaskUpdate(Id)

```csharp
public TaskUpdate(Id id)
```

Creates an update for the task with the given id. Every other property is [`Patch<T>.Missing`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/patch.md#missing>), so the update changes nothing until a property is set.

| Name | Type | Description |
|---|---|---|
| `id` | [`Id`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/id.md>) | Id of the task to edit. A `string`, `int` or `double` converts implicitly. |

## Properties

Every property except `Id` is a [`Patch<T>`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/patch.md>). `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`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/task-data.md#properties>).

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`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/id.md>) | required | Id of the task to edit. |
| `Parent` | `Patch<Id>` | root level | Moves the task under another parent. A value equal to [`SchedulingConfig.RootId`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/scheduling-config.md#rootid>) is read as `Null`. |
| `StartDate` | `Patch<`[`Moment`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/moment.md>)`>` | `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`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/task-data.md#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`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/pause.md>)`>>` | 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`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/task-data.md#tasktype>)), 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`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/calendar-mode.md>), no date property | start, duration | end |
| `Pauses` or `LevelingDelay`, no date property | start, duration | end |

- A `LevelingDelay` update with neither `StartDate` nor `EndDate` also 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 [`ScheduleFromEnd`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/scheduling-config.md#schedulefromend>) on, a `Pauses` or `LevelingDelay` update without dates keeps the end and derives the start instead.
- Under `CalendarMode.TaskInherited`, a `CalendarId` or `Parent` update also re-derives the end of each descendant leaf task that has no `CalendarId` of 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`](<https://docs.dhtmlx.com/planning-engine/net/api/core/results/mutation.md>).

## Methods

### DeepClone

```csharp
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

```csharp
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`](<https://docs.dhtmlx.com/planning-engine/net/api/project-apply.md>) and [`Project.Preview`](<https://docs.dhtmlx.com/planning-engine/net/api/project-preview.md>) 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`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/task-data.md>) rule or a [`ProjectData` rule](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/project-data.md#validation>), for example an unknown `CalendarId` or `Parent`. |

## Example

Move a task to a new start and make it one day longer:

```csharp
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`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/task-data.md>) - the record being edited
- [`SchedulingChanges`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/scheduling-changes.md>) - the change set that carries the update
- [`Patch<T>`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/patch.md>) - the three-state field type
- [`Mutation`](<https://docs.dhtmlx.com/planning-engine/net/api/core/results/mutation.md>) - a result entry to write back
- [Editing a project](<https://docs.dhtmlx.com/planning-engine/net/live-projects/editing-a-project.md>) - the full edit cycle
