ProjectTask
One row of a project plan – a piece of work, a summary that groups other tasks, or a milestone – as the Gantt chart, the PERT chart and the task board all read it.
public class ProjectTask : INotifyPropertyChanged
Inherits from / implements: INotifyPropertyChanged
Remarks
What it is for
A plan is a flat list of these with parent references, plus a list of TaskLink
objects between them: the shape a database table, a spreadsheet export or a web service already
has. Give the same two collections to a GanttChart, a PertChart and a
TaskBoard and they show one plan. Every property raises
PropertyChanged, so a bar dragged on the Gantt chart or a card moved on the board is
seen by the other charts at once, because they are all looking at the same objects.
Three kinds of task
- Work has a
Durationin working days (or aStartandFinishit is measured from). - A summary is any task that another task names as its
ParentId. Its dates, length and progress are rolled up from its subtasks, so its ownDurationis not used; aStarton a summary still holds all of its subtasks back. - A milestone has a
Durationof zero, orIsMilestoneset. It marks a moment – a sign-off, a release – and is drawn as a diamond.
Dates
The charts do not keep dates of their own: they schedule the plan by the critical-path method
(ProjectScheduler) and draw the result, so Start and
Finish are what was planned, and ScheduledTask.Start and
ScheduledTask.Finish are what the links allow. Only the date part of a
DateTime is kept, so a value read from a database as midnight UTC and one typed as a
local date plan the same day. Durations and lags count working days on the plan's calendar.
Board fields
Status is the task board's column, and Assignee and
Category are the fields it can split its lanes by. Rank is a card's
order within its column. None of these move a date.
Examples
A small website plan: two phases, a stand-alone task and a launch milestone. The phases are summaries because other tasks name them as their parent.
using System;
using System.Collections.ObjectModel;
ObservableCollection<ProjectTask> tasks = new ObservableCollection<ProjectTask>
{
new ProjectTask("design", "Design"), // summary: no duration of its own
new ProjectTask("brief", "Agree the brief", 3)
{
ParentId = "design",
Start = new DateTime(2026, 11, 2),
Assignee = "Priya",
Status = "Done",
Progress = 100
},
new ProjectTask("wire", "Wireframes", 5) { ParentId = "design", Assignee = "Priya", Status = "In progress", Progress = 40 },
new ProjectTask("build", "Build"),
new ProjectTask("front", "Front end", 10) { ParentId = "build", Assignee = "Tom", Status = "To do" },
new ProjectTask("api", "Order API", 8) { ParentId = "build", Assignee = "Aisha", Status = "To do" },
new ProjectTask("test", "User testing", 4) { Assignee = "Priya", Status = "To do" },
new ProjectTask("live", "Go live", 0) { Status = "To do" } // a milestone
};See also
Members at a glance
| Constructors | |
|---|---|
ProjectTask | Creates an empty task. Give it at least an Id; a task without one is left
out of the plan. |
ProjectTask | Creates a task with an id, a name and, optionally, a length in working days. |
| Properties | |
Assignee | Gets or sets who is doing the work. |
BaselineFinish | Gets or sets the originally agreed last working day, the other end of the baseline. |
BaselineStart | Gets or sets the originally agreed start, kept so the Gantt chart can show how far the task has moved since. |
Category | Gets or sets a grouping of the application's choosing, such as a workstream or a cost centre. |
Constraint | Gets or sets how the task's own Start or Finish holds it, in addition to
its links. |
Duration | Gets or sets the task's length in working days. |
Finish | Gets or sets the planned last working day of the task. |
Id | Gets or sets the identifier that links, subtasks and every chart event refer to the task by. |
IsCollapsed | Gets or sets whether a summary task starts closed on the Gantt chart, with its subtasks hidden. |
IsMilestone | Gets or sets whether the task is a milestone – a moment with no length, drawn as a diamond –
whatever its Duration says. |
Name | Gets or sets what the task is called: the text of its row, bar label, box and card, and what a screen reader announces. |
ParentId | Gets or sets the Id of the summary task this task sits under in the outline. |
Progress | Gets or sets how much of the task is done, as a percentage. |
Rank | Gets or sets the card's position within its column on the task board, lower first. |
Start | Gets or sets the planned start: the earliest date the task may begin. |
Status | Gets or sets the task's workflow state, such as "To do", "In progress" or "Done". |
Tag | Gets or sets any object the application wants to keep with the task, such as the database row it came from. |
| Methods | |
Clone | Creates a shallow copy of the task, with every property, Tag included. |
OnPropertyChanged | Raises PropertyChanged. A derived task with properties of its own calls this
from their setters so the charts see those changes too. |
ToString | Returns the task's name, for the debugger and for list boxes. |
| Events | |
PropertyChanged | Occurs when any property of the task changes. The charts listen to it to redraw. |
Constructors
ProjectTask
Creates an empty task. Give it at least an Id; a task without one is left
out of the plan.
ProjectTask
Creates a task with an id, a name and, optionally, a length in working days.
Parameters
id- The task's id, unique in its plan. It is what
TaskLinkobjects and other tasks'ParentIdrefer to. name- What the task is called on every chart.
duration- Length in working days; zero makes a milestone. Leave it out (null) for a
summary task, or for a task whose length comes from its
StartandFinish.
Example
ProjectTask phase = new ProjectTask("build", "Build"); // a summary
ProjectTask work = new ProjectTask("api", "Order API", 8) { ParentId = "build" };
ProjectTask signOff = new ProjectTask("signoff", "Client sign-off", 0); // a milestoneProperties
Assignee
Gets or sets who is doing the work.
- Value
- Any text, such as a person's name. The default is
null.
Remarks
The Gantt chart can show it in a column (GanttColumns.Assignee), a task board
card shows its initials, and a board whose lanes are by BoardLaneBy.Assignee has a
lane per assignee; dropping a card in another lane sets this property.
BaselineFinish
Gets or sets the originally agreed last working day, the other end of the baseline.
- Value
- A date; only its date part is kept. The default is
null.
See also
BaselineStart
Gets or sets the originally agreed start, kept so the Gantt chart can show how far the task has moved since.
- Value
- A date; only its date part is kept. The default is
null: no baseline.
Remarks
Drawn as a thin bar under the task's bar, from this date to BaselineFinish
(one day long when that is not set), when GanttChart.ShowBaselines is on.
Nothing is scheduled from it.
Example
Recording the plan as agreed, once it has been scheduled, so later slippage shows.
ProjectSchedule agreed = ProjectScheduler.Schedule(tasks, links);
foreach (ScheduledTask scheduled in agreed.Tasks)
{
scheduled.Task.BaselineStart = scheduled.Start;
scheduled.Task.BaselineFinish = scheduled.Finish;
}Category
Gets or sets a grouping of the application's choosing, such as a workstream or a cost centre.
- Value
- Any text. The default is
null.
Remarks
A task board whose lanes are by BoardLaneBy.Category has a lane per category,
and dropping a card in another lane sets this property. Nothing else reads it.
Constraint
- Value
- The default is
TaskConstraintKind.StartNoEarlierThan.
Example
// The venue is booked for 14 December: the launch event happens then, whatever slips before it.
ProjectTask launch = new ProjectTask("event", "Launch event", 1)
{
Start = new DateTime(2026, 12, 14),
Constraint = TaskConstraintKind.MustStartOn
};Duration
Gets or sets the task's length in working days.
- Value
- A whole number of working days; zero makes the task a milestone, and a negative value is read as
zero. The default is
null: the length is then the working days fromStarttoFinishinclusive when both are set, and otherwise one day.
Remarks
Weekends and holidays do not count, so a five-day task that starts on a Thursday finishes on the following Wednesday. A summary's own duration is not used: its length is rolled up from its subtasks.
When a chart changes the duration – a bar's end dragged, a cell typed – it clears
Finish as well, unless Constraint is
TaskConstraintKind.FinishNoEarlierThan, so the two never say different things.
Finish
Gets or sets the planned last working day of the task.
- Value
- A date; only its date part is kept. The default is
null.
Remarks
It is read in two cases only: to measure the length of a task whose Duration is
null, and as the date a TaskConstraintKind.FinishNoEarlierThan
constraint holds. Otherwise the finish is worked out from the start and the duration, and is
ScheduledTask.Finish.
Id
Gets or sets the identifier that links, subtasks and every chart event refer to the task by.
- Value
- Any string, compared exactly (case matters). The default is
null.
Remarks
A task whose id is null is left out of the plan without comment. When two
tasks share an id, the first one in the list is used and the other is reported as
ScheduleProblemKind.DuplicateTask.
Changing the id of a task that links or subtasks already refer to leaves them pointing at the old id; change those references too.
See also
IsCollapsed
Gets or sets whether a summary task starts closed on the Gantt chart, with its subtasks hidden.
- Value
- The default is
false: summaries start open. It has no effect on a task that is not a summary.
Remarks
It is read only until the reader opens or closes the summary; the chart then remembers the reader's choice and does not write it back here.
IsMilestone
Gets or sets whether the task is a milestone – a moment with no length, drawn as a diamond –
whatever its Duration says.
- Value
trueto make a milestone. The default isfalse; a task with a duration of zero is a milestone either way.
Name
Gets or sets what the task is called: the text of its row, bar label, box and card, and what a screen reader announces.
- Value
- Any text. The default is
null, in which case the charts show theId.
ParentId
Gets or sets the Id of the summary task this task sits under in the outline.
- Value
- The parent's id, or
null(the default) or an empty string for a top-level task.
Remarks
Naming a task as a parent is what makes it a summary: its dates are then rolled up from its
subtasks. An id that is not in the plan puts the task at the top level and is reported as
ScheduleProblemKind.UnknownParent; a parent that would make the task its own
ancestor is reported as ScheduleProblemKind.ParentCycle and is ignored in the same
way.
On a task board whose lanes are by phase (BoardLaneBy.Parent), dropping a card
in another lane sets this to that phase's id.
Progress
Gets or sets how much of the task is done, as a percentage.
- Value
- From 0 to 100. The default is 0. The value is stored as given; when the plan is scheduled a value below 0 is read as 0, above 100 as 100, and NaN or infinity as 0.
Remarks
A summary's own progress is not used: ScheduledTask.Progress for a summary
is its subtasks' progress weighted by their durations.
Rank
Gets or sets the card's position within its column on the task board, lower first.
- Value
- Any number. The default is
null: cards without a rank follow the ranked ones, in the order the tasks are listed.
Remarks
The board writes this when a card is moved, renumbering every card in the cell it lands in from 1 upwards. Nothing else reads it, so rearranging a board never moves a date.
Start
Gets or sets the planned start: the earliest date the task may begin.
- Value
- A date; only its date part is kept. The default is
null, which lets the task start as soon as its links, its summary and the project's start allow.
Remarks
Links may push the task later than this date, never earlier – unless
Constraint is TaskConstraintKind.MustStartOn, which holds the task to
it. A weekend or holiday is read as the next working day.
Dragging a bar on the Gantt chart, or typing in its Start cell, sets this property. The date
the task is actually scheduled on is ScheduledTask.Start.
See also
Status
Gets or sets the task's workflow state, such as "To do", "In progress" or "Done".
- Value
- Any text, compared exactly. The default is
null.
Remarks
The task board's columns are statuses: a card sits in the column whose
BoardColumn.Status matches this value, or in the first column when none does, and
moving a card sets it. The Gantt and PERT charts do not read it.
Tag
Gets or sets any object the application wants to keep with the task, such as the database row it came from.
- Value
- The default is
null. The charts never read it.
Methods
Clone
Creates a shallow copy of the task, with every property, Tag included.
Returns
A new task with the same values. Tag refers to the same object as the
original's.
Remarks
Handlers attached to the original's PropertyChanged event are not carried over:
the copy starts with none.
OnPropertyChanged
Raises PropertyChanged. A derived task with properties of its own calls this
from their setters so the charts see those changes too.
Parameters
propertyName- The name of the property that changed.
ToString
Returns the task's name, for the debugger and for list boxes.
Returns
Events
PropertyChanged
Occurs when any property of the task changes. The charts listen to it to redraw.
Remarks
Raised only when a value actually changes; setting a property to the value it already has raises nothing.