HypernovaDesktop Components · docs
Binarymission
WPF › Project Management › GanttChart

GanttChart

class.NET 6 / 8 / 10.NET Framework 4.8Binarymission.WPF.Controls.ProjectManagement

A Gantt chart: the plan as a task list beside a timeline of bars, with the links between the tasks, the milestones, the baselines and the critical path, scheduled on a working calendar and editable with the mouse or the keyboard alone.

public partial class GanttChart : Control

Inherits from / implements: Control

Remarks

Use it wherever work is planned against dates – a product launch, a fit-out, a release – to answer what a planner asks of a plan (when does it finish, what is late, which tasks have no slack) and to let them change it by dragging.

The plan

A plan is two lists that belong to the application: Tasks, a flat list of ProjectTask objects in which a subtask names its summary through ProjectTask.ParentId, and Links, the TaskLink dependencies between them – the shape a database table or a spreadsheet already has. An ObservableCollection is watched, and so is every task and link in it: change a property and the chart schedules again and redraws.

Scheduling

Dates are worked out by the critical-path method on working days – the days WorkingWeek names, less the Holidays, from ProjectStart. A task starts on its planned ProjectTask.Start or as soon as its links allow, whichever is later, and a summary spans its subtasks. The result is in Schedule, and ScheduleChanged says when it has been worked out again. Bad data never stops the chart: a link to a missing task, or a loop, is left out and reported in ProjectSchedule.Problems, and everything else is drawn.

The two panes

The task list on the left shows the outline and the Columns you choose; the timeline on the right shows a bar for each task, a diamond for each milestone and a bracket for each summary, at the scale Zoom sets. The panes scroll up and down together; the splitter between them sets GridWidth.

Editing

Drag a bar to move the task, its right-hand end to change its length, or the triangle under it to set its progress; drag from the dot past its end to another row to link the two finish-to-start. Press F2 to type into the current cell – name, start, days, % done or predecessors (outline numbers such as 2, 3SS+1). Every edit is offered first through TaskChanging or LinksChanging, which can cancel it, then made to the task or link object itself and announced by TaskChanged or LinksChanged. IsReadOnly allows looking only.

The keyboard

KeysWhat they do

Up, Down, Home, End, Page Up, Page Down

Move between rows.

Right, Left

Open or close a summary, or go to its first subtask or back; in other columns, move between cells.

F2; Enter or Space

Edit the current cell; raise TaskActivated.

Shift+Left, Shift+Right

Move the task a working day earlier or later.

Ctrl+Shift+Left, Ctrl+Shift+Right

Make it a working day shorter or longer.

Ctrl+Plus, Ctrl+Minus, Ctrl+0

Zoom in, out, or to fit the plan. Esc cancels a drag.

One plan, three views

Give the same lists to a PertChart and a TaskBoard and the three agree: they schedule the same objects with the same arithmetic, so a bar dragged here or a card moved on the board is seen by all of them.

Appearance

The chart draws itself and has no template. Control.Background, Control.Foreground and the font apply as usual; the bars, links and calendar have brush properties (BarBrush, CriticalBrush and the rest) whose defaults read on light and dark backgrounds alike, and in Windows high contrast the system colours replace them all. The chart always runs left to right, as a calendar does. ExportImage and Print draw the whole plan.

Examples

A window that plans a website relaunch, built in code so that it stands on its own; in XAML the lists are bound, as in <pm:GanttChart Tasks="{Binding Tasks}" Links="{Binding Links}" Zoom="Week" /> with xmlns:pm="clr-namespace:Binarymission.WPF.Controls.ProjectManagement;assembly=Binarymission.WPF.Controls.ProjectManagement".

using System;
using System.Collections.ObjectModel;
using System.Windows;
using Binarymission.WPF.Controls.ProjectManagement;

public sealed class PlanWindow : Window
{
    public PlanWindow()
    {
        var tasks = new ObservableCollection<ProjectTask>
        {
            new ProjectTask("design", "Design"),                     // a summary: it has subtasks
            new ProjectTask("wire", "Wireframes", 5)    { ParentId = "design", Assignee = "Priya Shah", Progress = 100 },
            new ProjectTask("look", "Visual design", 8) { ParentId = "design", Assignee = "Tom Ellis", Progress = 40 },
            new ProjectTask("build", "Build"),
            new ProjectTask("web", "Front end", 10)     { ParentId = "build", Assignee = "Ana Ruiz" },
            new ProjectTask("api", "Orders API", 12)    { ParentId = "build", Assignee = "Sam Okafor" },
            new ProjectTask("live", "Go live", 0),                    // no length: a milestone
        };
        var links = new ObservableCollection<TaskLink>
        {
            new TaskLink("wire", "look"),                             // finish-to-start
            new TaskLink("look", "web", TaskLinkType.StartToStart, 3), // 3 working days after it starts
            new TaskLink("wire", "api"),
            new TaskLink("web", "live"),
            new TaskLink("api", "live"),
        };

        var gantt = new GanttChart
        {
            Tasks = tasks,
            Links = links,
            ProjectStart = new DateTime(2026, 11, 2),
            Columns = GanttColumns.Default | GanttColumns.Assignee,
        };
        gantt.Holidays.Add(new DateTime(2026, 12, 25));

        // A finished task stays where it is, whichever way the reader tries to move it.
        gantt.TaskChanging += (sender, e) =>
            e.Cancel = e.Task.Progress >= 100 && (e.NewStart.HasValue || e.NewDuration.HasValue);
        gantt.ScheduleChanged += (sender, e) =>
            Title = "Website relaunch - finishes " + gantt.Schedule.ProjectFinish.ToString("d MMM yyyy");

        Content = gantt;
        Loaded += (sender, e) => gantt.ZoomToFit();
    }
}

See also

Members at a glance

Constructors
GanttChartCreates a Gantt chart with an empty plan: empty Tasks, Links and Holidays lists of its own, a Monday-to-Friday week and Week zoom. To share a plan, give several charts the same lists.
Properties
BarBrushGets or sets the fill of a task bar and a milestone diamond that are not on the critical path.
BaselineBrushGets or sets the fill of the thin baseline bar drawn under a task's bar while ShowBaselines is on.
ColumnsGets or sets which columns the task list shows beside the task's name.
CriticalBrushGets or sets the colour of the bars, milestones and links on the critical path, while ShowCriticalPath is on.
GridLineBrushGets or sets the colour of the lines between rows and columns, under the headers and beside the splitter.
GridWidthGets or sets the width of the task list, the left-hand pane; the timeline takes the rest.
HeaderBrushGets or sets the tint behind the column headings, the timeline's header rows and the splitter.
HolidaysGets or sets the dates that are not worked, beside the days WorkingWeek leaves out: bank holidays, a shutdown, a company day off.
IsReadOnlyGets or sets whether the reader can only look at the plan, and not change it.
LinkBrushGets or sets the colour of the arrows between bars that are not on the critical path.
LinksGets or sets the links between the tasks: which task waits for which, how, and with what lag.
LogicalChildrenGets the chart's logical children: the scroll bars and the cell editor, which therefore take the chart's resources and styles.
NonWorkingBrushGets or sets the tint behind the days that are not worked – weekends and Holidays – on the timeline and in its header.
ProgressBrushGets or sets what is painted over the finished part of a bar, from its start to its ProjectTask.Progress, and over the finished part of a summary's bracket.
ProjectStartGets or sets the first day work on the plan can happen.
RowHeightGets or sets the height of every row, in the task list and on the timeline alike.
ScheduleGets the plan as scheduled: every task's dates, float and outline number, the links that were honoured, the critical path, and what in the input could not be used.
SelectedTaskGets or sets the task the reader has chosen: the highlighted row and bar, and the row the keyboard works on.
SelectionBrushGets or sets the fill behind the selected row in the task list; a fainter copy marks the row across the timeline.
ShowBaselinesGets or sets whether each task's baseline – the dates first agreed – is drawn as a thin bar in BaselineBrush under its bar, so slippage shows at a glance.
ShowCriticalPathGets or sets whether the critical path – the tasks with no float, which decide when the plan finishes – is drawn in CriticalBrush, links included.
ShowLinksGets or sets whether the links between tasks are drawn as arrows between their bars.
ShowTodayGets or sets whether a line in TodayBrush is drawn down the timeline through today, with a notch in the header.
SummaryBrushGets or sets the colour of a summary task's bracket: the bar with downward points at each end that spans its subtasks.
TasksGets or sets the tasks of the plan: a flat list in outline order, in which a subtask names its summary through ProjectTask.ParentId.
TodayGets or sets the date the today line is drawn on.
TodayBrushGets or sets the colour of the today line, the notch above it, and today's date in the header.
VisualChildrenCountGets the number of elements the chart is made of: its three drawing panes, its three scroll bars and its cell editor.
WeekStartGets or sets the day a week begins on in the timeline's headers.
WorkingWeekGets or sets the days of the week on which work happens.
ZoomGets or sets how much time the timeline shows: how wide a day is, and what its two header rows label.
Methods
ArrangeOverrideLays out the task list, the splitter, the timeline and the scroll bars in the size the chart has been given.
CollapseAllCloses every summary task, leaving the top level of the outline. Raises TaskToggled for each one closed; a selected subtask hands the selection to its summary.
ExpandAllOpens every summary task, so that every task has a row. Raises TaskToggled for each one opened.
ExportImageDraws the whole chart as an image: every task, inside closed summaries too, beside the whole timeline, with the task list at its full width.
GetVisualChildReturns one of the elements the chart is made of.
IsExpandedTells whether a summary task is open, showing its subtasks.
MeasureOverrideSays how much room the chart wants: all it is given, up to 720 by 360 logical units.
OnCreateAutomationPeerGives UI Automation the chart as a tree of rows, so that a screen reader can read and work the plan.
OnDpiChangedRedraws for a new display scale, so that grid lines stay one device pixel wide and text is sharp.
OnIsKeyboardFocusedChangedShows or hides the focus rectangle round the current row, and on taking the focus tells a screen reader which row is current.
OnKeyDownCarries out the chart's keys: the arrows and page keys to move between rows and cells, F2 to edit, Enter and Space to activate, Shift and Ctrl+Shift with the arrows to move and stretch a task, Ctrl with Plus, Minus and 0 to zoom, and Esc to cancel a drag.
OnLinksChangedRaises LinksChanged. An override should call the base implementation, or handlers are not called.
OnLinksChangingRaises LinksChanging. An override should call the base implementation, or handlers are not called.
OnLostMouseCaptureCancels a drag, with no change, when something else takes the mouse – a dialog, or another window coming to the front.
OnMouseLeaveHides the bar handles and the tooltip when the pointer leaves the chart.
OnMouseLeftButtonDownActs on a click: selects the row or bar under the pointer, opens or closes a summary at its expander, and starts a drag on a bar, its end, its progress handle, its link dot or the splitter. A double-click raises TaskActivated.
OnMouseLeftButtonUpEnds a drag and makes the change it describes, through TaskChanging or LinksChanging. A press that never moved far enough to be a drag changes nothing.
OnMouseMoveFollows the pointer: carries on a drag, scrolling when it passes the edge of the view, or shows the handles of the bar under the pointer and, after the hover time, a tooltip describing its task.
OnMouseRightButtonDownSelects the task under the pointer, so that a context menu acts on the task that was clicked.
OnMouseWheelScrolls the rows by the system's wheel setting; with Shift, scrolls the pane under the pointer sideways; with Ctrl, zooms about the pointer.
OnPropertyChangedRedraws when a property the drawing reads from the control itself changes: the font, Foreground, Background or UIElement.IsEnabled.
OnQueryCursorShows what a press would do: a sideways arrow over the splitter, a bar's end or its progress handle, a cross over a link dot, and a hand over a bar that can be moved or an expander.
OnRenderDraws the background, the splitter and the corner above the vertical scroll bar. The task list and the timeline are drawn by panes of their own, so that scrolling or a drag redraws only what changed.
OnScheduleChangedRaises ScheduleChanged. An override should call the base implementation, or handlers are not called.
OnSelectedTaskChangedRaises SelectedTaskChanged. An override should call the base implementation, or handlers are not called.
OnTaskActivatedRaises TaskActivated. An override should call the base implementation, or handlers are not called.
OnTaskChangedRaises TaskChanged. An override should call the base implementation, or handlers are not called.
OnTaskChangingRaises TaskChanging. An override should call the base implementation, or handlers are not called.
OnTaskToggledRaises TaskToggled. An override should call the base implementation, or handlers are not called.
OnZoomChangedRaises ZoomChanged. An override should call the base implementation, or handlers are not called.
PrintAsks the reader for a printer and prints the whole chart on one page, as ExportImage draws it, shrunk to fit the printable area when it is larger.
RescheduleSchedules the plan again now and redraws.
ScrollToTaskBrings a task into view: opens the summaries above it, scrolls its row into view, and scrolls the timeline to its bar when any of the bar is out of sight.
ScrollToTodayScrolls the timeline sideways so that today is in view, a third of the way across the pane.
SetExpandedOpens or closes one summary task.
ZoomInShows less time in more detail: one step finer through Year, Quarter, Month, Week and Day.
ZoomOutShows more time in less detail: one step coarser through Day, Week, Month, Quarter and Year.
ZoomToFitChooses the finest Zoom at which the whole plan, first day to last, fits the timeline pane, and scrolls to the plan's first day.
Events
LinksChangedOccurs after an edit the reader made has added links to Links or removed them. Save the links here to keep the edit.
LinksChangingOccurs when the reader is about to change the links into a task – by drawing a link between two bars, or by typing into the Predecessors cell. Cancel it to refuse the edit.
ScheduleChangedOccurs after the plan has been scheduled again: once the chart is loaded, and whenever a task, a link, one of the lists or a calendar setting has changed.
SelectedTaskChangedOccurs when SelectedTask changes, whether the reader chose another row or the application set the property.
TaskActivatedOccurs when the reader asks to open a task: by double-clicking its row or bar, or by pressing Enter or Space on the selected row. The task is already selected.
TaskChangedOccurs after an edit the reader made has been written to a task: its start, length, progress or name.
TaskChangingOccurs when the reader is about to change a task – by dragging its bar, by a key or by typing into a cell – before anything has changed. Cancel it to refuse the edit.
TaskToggledOccurs when a summary task is opened or closed – by its expander, the arrow keys, SetExpanded, ExpandAll, CollapseAll, or because a task inside it was selected.
ZoomChangedOccurs when Zoom changes, from code or from the reader's Ctrl+wheel, Ctrl+Plus, Ctrl+Minus or Ctrl+0.
Fields
BarBrushPropertyIdentifies the BarBrush dependency property.
BaselineBrushPropertyIdentifies the BaselineBrush dependency property.
ColumnsPropertyIdentifies the Columns dependency property.
CriticalBrushPropertyIdentifies the CriticalBrush dependency property.
GridLineBrushPropertyIdentifies the GridLineBrush dependency property.
GridWidthPropertyIdentifies the GridWidth dependency property.
HeaderBrushPropertyIdentifies the HeaderBrush dependency property.
HolidaysPropertyIdentifies the Holidays dependency property.
IsReadOnlyPropertyIdentifies the IsReadOnly dependency property.
LinkBrushPropertyIdentifies the LinkBrush dependency property.
LinksPropertyIdentifies the Links dependency property.
NonWorkingBrushPropertyIdentifies the NonWorkingBrush dependency property.
ProgressBrushPropertyIdentifies the ProgressBrush dependency property.
ProjectStartPropertyIdentifies the ProjectStart dependency property.
RowHeightPropertyIdentifies the RowHeight dependency property.
SelectedTaskPropertyIdentifies the SelectedTask dependency property.
SelectionBrushPropertyIdentifies the SelectionBrush dependency property.
ShowBaselinesPropertyIdentifies the ShowBaselines dependency property.
ShowCriticalPathPropertyIdentifies the ShowCriticalPath dependency property.
ShowLinksPropertyIdentifies the ShowLinks dependency property.
ShowTodayPropertyIdentifies the ShowToday dependency property.
SummaryBrushPropertyIdentifies the SummaryBrush dependency property.
TasksPropertyIdentifies the Tasks dependency property.
TodayBrushPropertyIdentifies the TodayBrush dependency property.
TodayPropertyIdentifies the Today dependency property.
WeekStartPropertyIdentifies the WeekStart dependency property.
WorkingWeekPropertyIdentifies the WorkingWeek dependency property.
ZoomPropertyIdentifies the Zoom dependency property.

Constructors

GanttChart

public GanttChart()

Creates a Gantt chart with an empty plan: empty Tasks, Links and Holidays lists of its own, a Monday-to-Friday week and Week zoom. To share a plan, give several charts the same lists.

Properties

BarBrush

public Brush BarBrush

Gets or sets the fill of a task bar and a milestone diamond that are not on the critical path.

Value
The default is an opaque mid blue, #4A8FD6. null leaves bars unfilled.
Designer category
Brush
Remarks

Critical bars use CriticalBrush while ShowCriticalPath is on, and the finished part of every bar is darkened by ProgressBrush. Summaries are drawn in SummaryBrush. In Windows high contrast the system colours are used instead.

Example
<pm:GanttChart BarBrush="#2E7D32" CriticalBrush="#C62828" ProgressBrush="#66000000"
               TodayBrush="#1565C0" NonWorkingBrush="#14000000" />
See also

BaselineBrush

public Brush BaselineBrush

Gets or sets the fill of the thin baseline bar drawn under a task's bar while ShowBaselines is on.

Value
The default is a light grey, #A3ABB5.
Designer category
Brush
Remarks

In Windows high contrast the system colours are used instead.

Columns

public GanttColumns Columns

Gets or sets which columns the task list shows beside the task's name.

Value
A combination of GanttColumns flags. The default is GanttColumns.Default: outline number, name, start, finish, days and predecessors. The name is always shown.
Remarks

The order is fixed – #, Task, Start, Finish, Days, % done, Assignee, Predecessors – and so are the English headings. Name, Start, Days, % done and Predecessors can be typed into with F2. For example GanttColumns.Wbs | GanttColumns.Name | GanttColumns.Assignee.

CriticalBrush

public Brush CriticalBrush

Gets or sets the colour of the bars, milestones and links on the critical path, while ShowCriticalPath is on.

Value
The default is a red-orange, #E3552F. null draws critical bars in BarBrush.
Designer category
Brush
Remarks

It is also the colour of the border a cell editor shows when what was typed cannot be read. In Windows high contrast the system colours are used instead.

GridLineBrush

public Brush GridLineBrush

Gets or sets the colour of the lines between rows and columns, under the headers and beside the splitter.

Value
The default is grey at 20% opacity (#33808080), which shows on a light or a dark background alike.
Designer category
Brush
Remarks

In Windows high contrast the system colours are used instead.

GridWidth

public double GridWidth

Gets or sets the width of the task list, the left-hand pane; the timeline takes the rest.

Value
In logical units (1/96 inch). The default is 420. NaN or an infinity is read as 420, and a negative width as 0, which hides the list.
Remarks

It is never drawn wider than leaves room for the splitter and the vertical scroll bar. Dragging the splitter sets it, keeping both panes at least 48 units wide, without removing a binding; Esc during the drag puts it back.

HeaderBrush

public Brush HeaderBrush

Gets or sets the tint behind the column headings, the timeline's header rows and the splitter.

Value
The default is grey at 7% opacity (#12808080), laid over Background.
Designer category
Brush
Remarks

In Windows high contrast the system colours are used instead.

Holidays

public IList<DateTime> Holidays

Gets or sets the dates that are not worked, beside the days WorkingWeek leaves out: bank holidays, a shutdown, a company day off.

Value
The non-working dates; only the date part of each is read. The default is an empty list of the chart's own; setting null gives a new empty one.
Remarks

A task that runs across a holiday is a day longer on the calendar, and the day is shaded at Day and Week zoom. An ObservableCollection is watched: gantt.Holidays.Add(new DateTime(2026, 12, 25)) reschedules at once.

IsReadOnly

public bool IsReadOnly

Gets or sets whether the reader can only look at the plan, and not change it.

Value
true to stop dragging bars, drawing links, typing into cells and keyboard moves. The default is false.
Remarks

Selecting, scrolling, zooming, opening summaries and resizing the task list still work, and code can still change the plan. Turning it on cancels a drag and drops an open edit. To allow some edits only, cancel TaskChanging instead.

LinkBrush

public Brush LinkBrush

Gets or sets the colour of the arrows between bars that are not on the critical path.

Value
The default is a mid grey, #87919C. null draws them grey.
Designer category
Brush
Remarks

Links on the critical path use CriticalBrush; the selected task's links are drawn in Foreground, heavier. In Windows high contrast the system colours are used instead.

See also

LogicalChildren

protected override IEnumerator LogicalChildren

Gets the chart's logical children: the scroll bars and the cell editor, which therefore take the chart's resources and styles.

Value
An enumerator over the scroll bars and the editor; the drawing panes are not included.

NonWorkingBrush

public Brush NonWorkingBrush

Gets or sets the tint behind the days that are not worked – weekends and Holidays – on the timeline and in its header.

Value
The default is grey at 9% opacity (#17808080). null shades nothing.
Designer category
Brush
Remarks

The tint is drawn only at Day and Week Zoom, where a day is wide enough to see. In Windows high contrast the system colours are used instead.

ProgressBrush

public Brush ProgressBrush

Gets or sets what is painted over the finished part of a bar, from its start to its ProjectTask.Progress, and over the finished part of a summary's bracket.

Value
The default is a translucent black (#5C000000), which darkens whatever colour the bar is, critical or not. null shows no progress.
Designer category
Brush
Remarks

A translucent brush keeps working whatever BarBrush and CriticalBrush are; an opaque one paints the finished part a colour of its own. In Windows high contrast the system colours are used instead.

ProjectStart

public DateTime? ProjectStart

Gets or sets the first day work on the plan can happen.

Value
The project's first possible day, or null to take it from the tasks: the earliest planned ProjectTask.Start, else the earliest planned ProjectTask.Finish, else today. The default is null.
Remarks

A date that is not worked is read as the next working day. No task is scheduled before it except one that TaskConstraintKind.MustStartOn an earlier date.

RowHeight

public double RowHeight

Gets or sets the height of every row, in the task list and on the timeline alike.

Value
In logical units (1/96 inch). The default is 28; values are kept between 16 and 200, and NaN is read as 28.
Remarks

A bar is half the row high, never less than 6, so taller rows give bars and handles that are easier to grab.

Schedule

public ProjectSchedule Schedule

Gets the plan as scheduled: every task's dates, float and outline number, the links that were honoured, the critical path, and what in the input could not be used.

Value
The current schedule; never null.
Remarks

A change only marks the schedule stale; it is worked out again when next needed, by a redraw or by reading this, so the value is always current. A chart that is not loaded schedules afresh on every read. ScheduledTask.Task leads back to your own task.

Example
foreach (ScheduledTask task in gantt.Schedule.Tasks)
{
    if (task.IsCritical && !task.IsSummary)
        Console.WriteLine($"{task.Wbs} {task.Name}: {task.Start:d} to {task.Finish:d}");
}
See also

SelectedTask

public ProjectTask SelectedTask

Gets or sets the task the reader has chosen: the highlighted row and bar, and the row the keyboard works on.

Value
A task in Tasks, or null for none; the default. It binds two-way by default.
Remarks

Setting a task inside a closed summary opens the summaries above it and scrolls it into view. A task not in Tasks is not selected: the property is cleared once the plan is current, as it is when the selected task is removed. Closing the summary the selected task is in moves the selection to the summary. Bind it to a PertChart's or TaskBoard's SelectedTask to keep the views in step.

See also

SelectionBrush

public Brush SelectionBrush

Gets or sets the fill behind the selected row in the task list; a fainter copy marks the row across the timeline.

Value
The default is null: the system highlight colour at about a quarter opacity, so the row's text stays readable in Foreground.
Designer category
Brush
Remarks

Choose a light or translucent brush: the selected row's text is drawn over it in the ordinary text colour. In Windows high contrast the system colours are used instead.

ShowBaselines

public bool ShowBaselines

Gets or sets whether each task's baseline – the dates first agreed – is drawn as a thin bar in BaselineBrush under its bar, so slippage shows at a glance.

Value
The default is false.
Remarks

A task has a baseline when ProjectTask.BaselineStart is set; it runs to ProjectTask.BaselineFinish, or covers one day without it.

Example
// Freeze the plan as it stands as the baseline, then show it.
foreach (ScheduledTask scheduled in gantt.Schedule.Tasks)
{
    scheduled.Task.BaselineStart = scheduled.Start;
    scheduled.Task.BaselineFinish = scheduled.Finish;
}
gantt.ShowBaselines = true;

ShowCriticalPath

public bool ShowCriticalPath

Gets or sets whether the critical path – the tasks with no float, which decide when the plan finishes – is drawn in CriticalBrush, links included.

Value
The default is true.
Remarks

Turning it off changes only the colours; the critical tasks are still in ProjectSchedule.CriticalPath.

ShowToday

public bool ShowToday

Gets or sets whether a line in TodayBrush is drawn down the timeline through today, with a notch in the header.

Value
The default is true.
Remarks

Today is Today, or the computer's date. Nothing is drawn when today is outside the timeline.

SummaryBrush

public Brush SummaryBrush

Gets or sets the colour of a summary task's bracket: the bar with downward points at each end that spans its subtasks.

Value
The default is a slate grey, #5A6470.
Designer category
Brush
Remarks

In Windows high contrast the system colours are used instead.

Tasks

public IList<ProjectTask> Tasks

Gets or sets the tasks of the plan: a flat list in outline order, in which a subtask names its summary through ProjectTask.ParentId.

Value
The tasks to schedule and draw. The default is an empty list of the chart's own; setting null gives a new empty one, so it is never null.
Remarks

The list's order is the order of the rows within each summary. A task is a summary when another task names it as its parent. Tasks with no ProjectTask.Id are left out, and a repeated id is reported in ProjectSchedule.Problems.

While the chart is loaded an ObservableCollection or a BindingList<T> is watched, and so is every task in it. A plain List<T> is read when assigned; call Reschedule after changing one. Assigning a new list cancels a drag and drops an open cell edit.

Example
gantt.Tasks.Add(new ProjectTask("qa", "Acceptance testing", 4) { ParentId = "build", Assignee = "Lena Fischer" });
gantt.Links.Add(new TaskLink("api", "qa"));   // scheduled and drawn with no further call
See also

Today

public DateTime? Today

Gets or sets the date the today line is drawn on.

Value
The date to treat as today, or null for the computer's date, read at each redraw. The default is null.
Remarks

It moves the ShowToday line and the place ScrollToToday goes to, and no date in the schedule. Set it to show a plan as at a status date.

TodayBrush

public Brush TodayBrush

Gets or sets the colour of the today line, the notch above it, and today's date in the header.

Value
The default is a clear green, #12A17B.
Designer category
Brush
Remarks

The line is drawn while ShowToday is on. In Windows high contrast the system colours are used instead.

VisualChildrenCount

protected override int VisualChildrenCount

Gets the number of elements the chart is made of: its three drawing panes, its three scroll bars and its cell editor.

Value
Always 7.

WeekStart

public DayOfWeek WeekStart

Gets or sets the day a week begins on in the timeline's headers.

Value
The default is Monday.
Remarks

At Week zoom each week is labelled by this day. Scheduling is unaffected; WorkingWeek decides that.

WorkingWeek

public WorkingWeek WorkingWeek

Gets or sets the days of the week on which work happens.

Value
A combination of day flags. The default is WorkingWeek.Weekdays, Monday to Friday; WorkingWeek.None is read as every day.
Remarks

Durations and lags count working days, so a five-day task starting on a Thursday finishes the Wednesday after, and the weekend between is shaded. In XAML: WorkingWeek="Sunday, Monday, Tuesday, Wednesday, Thursday".

See also

Zoom

public GanttZoom Zoom

Gets or sets how much time the timeline shows: how wide a day is, and what its two header rows label.

Value
The default is GanttZoom.Week; a value outside GanttZoom is read as Week.
Remarks

A day is 32 logical units (1/96 inch) wide at Day, 14 at Week, 4 at Month, 1.6 at Quarter and 0.6 at Year; weekends and holidays are shaded at Day and Week. A change keeps the date in the middle of the timeline (or under the pointer, for Ctrl+wheel) where it is, and raises ZoomChanged.

See also

Methods

ArrangeOverride

protected override Size ArrangeOverride(Size arrangeSize)

Lays out the task list, the splitter, the timeline and the scroll bars in the size the chart has been given.

Parameters
arrangeSize
The final size, in logical units.
Returns

arrangeSize: the chart uses all of it.

Remarks

Scrolls asked for before the first layout – by ZoomToFit, ScrollToTask and the rest – are carried out once this has run.

CollapseAll

public void CollapseAll()

Closes every summary task, leaving the top level of the outline. Raises TaskToggled for each one closed; a selected subtask hands the selection to its summary.

ExpandAll

public void ExpandAll()

Opens every summary task, so that every task has a row. Raises TaskToggled for each one opened.

ExportImage

public BitmapSource ExportImage(double dpi

Draws the whole chart as an image: every task, inside closed summaries too, beside the whole timeline, with the task list at its full width.

Parameters
dpi
The resolution in dots per inch; 96, the default, gives one pixel per logical unit, and 192 an image twice as sharp for print.
Returns

The image, frozen, so that it can be saved or handed to another thread.

Exceptions
ArgumentOutOfRangeException
dpi is not a positive number.
Remarks

Selection, focus and the scroll position are not drawn, and the image uses the chart's current Zoom, colours and font. The chart need not be on screen: one made only for exporting reads its plan afresh.

An image that would be wider or taller than 16,384 pixels, or larger than 128 megapixels, is made at the highest resolution below dpi that fits; its DpiX says which.

Example
BitmapSource image = gantt.ExportImage(144);
var png = new PngBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(image));
using (FileStream file = File.Create("Relaunch plan.png"))
    png.Save(file);
See also

GetVisualChild

protected override Visual GetVisualChild(int index)

Returns one of the elements the chart is made of.

Parameters
index
From 0 to VisualChildrenCount – 1, in drawing order: the task list, the timeline, the overlay, then the scroll bars and the editor.
Returns

The element at that position.

Exceptions
ArgumentOutOfRangeException
index is outside that range.

IsExpanded

public bool IsExpanded(ProjectTask task)

Tells whether a summary task is open, showing its subtasks.

Parameters
task
The task to ask about.
Returns

true for an open summary; false for a closed one, a task with no subtasks, null, or a task not in the plan.

MeasureOverride

protected override Size MeasureOverride(Size constraint)

Says how much room the chart wants: all it is given, up to 720 by 360 logical units.

Parameters
constraint
The room available, in logical units; either side may be infinite.
Returns

The smaller of constraint and 720 by 360.

Remarks

A chart shows as much of a plan as fits and scrolls the rest, so it has no natural size; give it a size, or put it where it is stretched (a Grid cell or a DockPanel's last child), rather than in a StackPanel.

OnCreateAutomationPeer

protected override AutomationPeer OnCreateAutomationPeer()

Gives UI Automation the chart as a tree of rows, so that a screen reader can read and work the plan.

Returns

The chart's automation peer.

Remarks

Each row is a tree item named with what its bar shows in pictures – its dates, length, progress, and its float or that it is critical – and can be selected, opened or closed, scrolled into view and invoked (which raises TaskActivated).

OnDpiChanged

protected override void OnDpiChanged(DpiScale oldDpi, DpiScale newDpi)

Redraws for a new display scale, so that grid lines stay one device pixel wide and text is sharp.

Parameters
oldDpi
The scale before.
newDpi
The scale now.

OnIsKeyboardFocusedChanged

protected override void OnIsKeyboardFocusedChanged(DependencyPropertyChangedEventArgs e)

Shows or hides the focus rectangle round the current row, and on taking the focus tells a screen reader which row is current.

Parameters
e
The old and new values of UIElement.IsKeyboardFocused.

OnKeyDown

protected override void OnKeyDown(KeyEventArgs e)

Carries out the chart's keys: the arrows and page keys to move between rows and cells, F2 to edit, Enter and Space to activate, Shift and Ctrl+Shift with the arrows to move and stretch a task, Ctrl with Plus, Minus and 0 to zoom, and Esc to cancel a drag.

Parameters
e
The key. Keys the chart uses are marked handled; others, and any key with Alt, are left for the window.
Remarks

The arrows are always taken, even at the first or last row, so they never move focus out of the chart by surprise. The class remarks list every key.

OnLinksChanged

protected virtual void OnLinksChanged(EventArgs e)

Raises LinksChanged. An override should call the base implementation, or handlers are not called.

Parameters
e
Empty event data.

OnLinksChanging

protected virtual void OnLinksChanging(LinksChangingEventArgs e)

Raises LinksChanging. An override should call the base implementation, or handlers are not called.

Parameters
e
The proposed change; set CancelEventArgs.Cancel to refuse it.

OnLostMouseCapture

protected override void OnLostMouseCapture(MouseEventArgs e)

Cancels a drag, with no change, when something else takes the mouse – a dialog, or another window coming to the front.

Parameters
e
The event data.

OnMouseLeave

protected override void OnMouseLeave(MouseEventArgs e)

Hides the bar handles and the tooltip when the pointer leaves the chart.

Parameters
e
The event data.

OnMouseLeftButtonDown

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)

Acts on a click: selects the row or bar under the pointer, opens or closes a summary at its expander, and starts a drag on a bar, its end, its progress handle, its link dot or the splitter. A double-click raises TaskActivated.

Parameters
e
The click.
Remarks

A click while a cell is being edited first commits the edit; when the text cannot be read, the editor stays open and the click does nothing more. An override should call the base implementation.

OnMouseLeftButtonUp

protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)

Ends a drag and makes the change it describes, through TaskChanging or LinksChanging. A press that never moved far enough to be a drag changes nothing.

Parameters
e
The release.

OnMouseMove

protected override void OnMouseMove(MouseEventArgs e)

Follows the pointer: carries on a drag, scrolling when it passes the edge of the view, or shows the handles of the bar under the pointer and, after the hover time, a tooltip describing its task.

Parameters
e
The move.

OnMouseRightButtonDown

protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)

Selects the task under the pointer, so that a context menu acts on the task that was clicked.

Parameters
e
The click. It is left unhandled, so the chart's FrameworkElement.ContextMenu still opens.
Example
<pm:GanttChart x:Name="gantt">
    <pm:GanttChart.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Open task" Click="OnOpenTask" />   <!-- acts on gantt.SelectedTask -->
        </ContextMenu>
    </pm:GanttChart.ContextMenu>
</pm:GanttChart>

OnMouseWheel

protected override void OnMouseWheel(MouseWheelEventArgs e)

Scrolls the rows by the system's wheel setting; with Shift, scrolls the pane under the pointer sideways; with Ctrl, zooms about the pointer.

Parameters
e
The wheel turn.

OnPropertyChanged

protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)

Redraws when a property the drawing reads from the control itself changes: the font, Foreground, Background or UIElement.IsEnabled.

Parameters
e
The property that changed, with its old and new values.
Remarks

An override should call the base implementation.

OnQueryCursor

protected override void OnQueryCursor(QueryCursorEventArgs e)

Shows what a press would do: a sideways arrow over the splitter, a bar's end or its progress handle, a cross over a link dot, and a hand over a bar that can be moved or an expander.

Parameters
e
The event data, whose Cursor is set.

OnRender

protected override void OnRender(DrawingContext drawingContext)

Draws the background, the splitter and the corner above the vertical scroll bar. The task list and the timeline are drawn by panes of their own, so that scrolling or a drag redraws only what changed.

Parameters
drawingContext
Where to draw.

OnScheduleChanged

protected virtual void OnScheduleChanged(EventArgs e)

Raises ScheduleChanged. An override should call the base implementation, or handlers are not called.

Parameters
e
Empty event data.

OnSelectedTaskChanged

protected virtual void OnSelectedTaskChanged(EventArgs e)

Raises SelectedTaskChanged. An override should call the base implementation, or handlers are not called.

Parameters
e
Empty event data.

OnTaskActivated

protected virtual void OnTaskActivated(TaskEventArgs e)

Raises TaskActivated. An override should call the base implementation, or handlers are not called.

Parameters
e
The task that was activated.

OnTaskChanged

protected virtual void OnTaskChanged(TaskEventArgs e)

Raises TaskChanged. An override should call the base implementation, or handlers are not called.

Parameters
e
The task that changed.

OnTaskChanging

protected virtual void OnTaskChanging(TaskChangingEventArgs e)

Raises TaskChanging. An override should call the base implementation, or handlers are not called.

Parameters
e
The proposed change; set CancelEventArgs.Cancel to refuse it.

OnTaskToggled

protected virtual void OnTaskToggled(TaskEventArgs e)

Raises TaskToggled. An override should call the base implementation, or handlers are not called.

Parameters
e
The summary that was opened or closed.

OnZoomChanged

protected virtual void OnZoomChanged(EventArgs e)

Raises ZoomChanged. An override should call the base implementation, or handlers are not called.

Parameters
e
Empty event data.

Print

public void Print(string description)

Asks the reader for a printer and prints the whole chart on one page, as ExportImage draws it, shrunk to fit the printable area when it is larger.

Parameters
description
The name of the job in the printer's queue; null or empty for "Gantt chart".
Remarks

Nothing is printed if the reader cancels the print dialog. A long plan at a fine zoom is shrunk a long way; choose a coarser Zoom first, or close summaries, for a readable page.

Reschedule

public void Reschedule()

Schedules the plan again now and redraws.

Remarks

Needed only after changing a plain List<T> or array, or a task in one; observable collections and their tasks are watched. Tasks newly added to a plain list are watched from here on. ScheduleChanged is raised before this returns.

ScrollToTask

public void ScrollToTask(ProjectTask task)

Brings a task into view: opens the summaries above it, scrolls its row into view, and scrolls the timeline to its bar when any of the bar is out of sight.

Parameters
task
The task to show. Nothing happens for null or a task that is not in the plan.
Remarks

The selection does not change; set SelectedTask as well to highlight it. Called before the chart has a size, it waits for the first layout.

Example
ProjectTask late = gantt.Schedule.Tasks.First(t => t.TotalFloat < 0).Task;
gantt.SelectedTask = late;
gantt.ScrollToTask(late);

ScrollToToday

public void ScrollToToday()

Scrolls the timeline sideways so that today is in view, a third of the way across the pane.

Remarks

Today is Today, or the computer's date. The rows do not scroll. Called before the chart has a size, it waits for the first layout.

SetExpanded

public void SetExpanded(ProjectTask task, bool expanded)

Opens or closes one summary task.

Parameters
task
The summary. Nothing happens for null, a task not in the plan, or one with no subtasks.
expanded
true to show its subtasks; false to hide them.
Remarks

Raises TaskToggled when the summary changes. Closing one that holds the selected task moves the selection to it.

ZoomIn

public void ZoomIn()

Shows less time in more detail: one step finer through Year, Quarter, Month, Week and Day.

Remarks

The date in the middle of the timeline stays where it is. At Day zoom nothing changes. The reader's Ctrl+Plus does the same, and Ctrl with the wheel zooms about the pointer.

See also

ZoomOut

public void ZoomOut()

Shows more time in less detail: one step coarser through Day, Week, Month, Quarter and Year.

Remarks

The date in the middle of the timeline stays where it is. At Year zoom nothing changes. The reader's Ctrl+Minus does the same.

See also

ZoomToFit

public void ZoomToFit()

Chooses the finest Zoom at which the whole plan, first day to last, fits the timeline pane, and scrolls to the plan's first day.

Remarks

Called before the chart has a size – from a constructor, say – it waits for the first layout and then fits. An empty plan is left as it is. When even Year zoom is too fine the chart is set to Year. The reader's Ctrl+0 does the same.

Example
gantt.Loaded += (sender, e) => gantt.ZoomToFit();

Events

LinksChanged

public event EventHandler LinksChanged

Occurs after an edit the reader made has added links to Links or removed them. Save the links here to keep the edit.

See also

LinksChanging

public event EventHandler<LinksChangingEventArgs> LinksChanging

Occurs when the reader is about to change the links into a task – by drawing a link between two bars, or by typing into the Predecessors cell. Cancel it to refuse the edit.

Remarks

Drawing adds one link; typing replaces the links into the task that differ from the ones typed, keeping those typed as they already are. A link the scheduler would refuse – a loop, a repeat, a summary linked to its own subtask – never gets this far: the reader is told why instead. When nobody cancels, the links are removed from and added to Links and LinksChanged is raised. When Links is read-only the reader is told so, and the event is not raised.

See also

ScheduleChanged

public event EventHandler ScheduleChanged

Occurs after the plan has been scheduled again: once the chart is loaded, and whenever a task, a link, one of the lists or a calendar setting has changed.

Remarks

Changes that arrive together – a board re-ranking a column, a loop setting twenty properties – are scheduled once and announced once, from the dispatcher, so a handler sees the finished result and may change the plan again. Reschedule raises it before returning. A chart that is not loaded does not raise it.

Example
gantt.ScheduleChanged += (sender, e) =>
{
    finishText.Text = gantt.Schedule.ProjectFinish.ToLongDateString();
    problemList.ItemsSource = gantt.Schedule.Problems;   // each one reads as a sentence
};

SelectedTaskChanged

public event EventHandler SelectedTaskChanged

Occurs when SelectedTask changes, whether the reader chose another row or the application set the property.

TaskActivated

public event EventHandler<TaskEventArgs> TaskActivated

Occurs when the reader asks to open a task: by double-clicking its row or bar, or by pressing Enter or Space on the selected row. The task is already selected.

Example
gantt.TaskActivated += (sender, e) => MessageBox.Show($"{e.Task.Name}: {e.Task.Assignee}, {e.Task.Progress:0}% done");

TaskChanged

public event EventHandler<TaskEventArgs> TaskChanged

Occurs after an edit the reader made has been written to a task: its start, length, progress or name.

Remarks

Raised once per edit, before the plan is scheduled again; save the task here to keep the edit, and read the dates that follow from it in ScheduleChanged.

See also

TaskChanging

public event EventHandler<TaskChangingEventArgs> TaskChanging

Occurs when the reader is about to change a task – by dragging its bar, by a key or by typing into a cell – before anything has changed. Cancel it to refuse the edit.

Remarks

The event data names the task, how the edit was made and the new values (null for what is not changing). When nobody cancels, the chart writes the values to the ProjectTask, raises TaskChanged and schedules again. Every edit the chart makes comes through here, which makes it the one place for rules such as "a signed-off task cannot move"; setting a task's properties in code does not raise it.

Tip

A moved task keeps its TaskConstraintKind.StartNoEarlierThan constraint, so a bar dropped earlier than its links allow is drawn where the links put it.

Example
gantt.TaskChanging += (sender, e) =>
{
    if (e.Task.Status == "Signed off")
    {
        e.Cancel = true;
        MessageBox.Show(e.Task.Name + " is signed off and cannot be changed.");
    }
};
See also

TaskToggled

public event EventHandler<TaskEventArgs> TaskToggled

Occurs when a summary task is opened or closed – by its expander, the arrow keys, SetExpanded, ExpandAll, CollapseAll, or because a task inside it was selected.

Remarks

Raised once for each summary that changes. Which summaries are open belongs to the chart: ProjectTask.IsCollapsed only sets how a summary starts, and is not written back.

ZoomChanged

public event EventHandler ZoomChanged

Occurs when Zoom changes, from code or from the reader's Ctrl+wheel, Ctrl+Plus, Ctrl+Minus or Ctrl+0.

Fields

BarBrushProperty static

public static readonly DependencyProperty BarBrushProperty

Identifies the BarBrush dependency property.

BaselineBrushProperty static

public static readonly DependencyProperty BaselineBrushProperty

Identifies the BaselineBrush dependency property.

ColumnsProperty static

public static readonly DependencyProperty ColumnsProperty

Identifies the Columns dependency property.

CriticalBrushProperty static

public static readonly DependencyProperty CriticalBrushProperty

Identifies the CriticalBrush dependency property.

GridLineBrushProperty static

public static readonly DependencyProperty GridLineBrushProperty

Identifies the GridLineBrush dependency property.

GridWidthProperty static

public static readonly DependencyProperty GridWidthProperty

Identifies the GridWidth dependency property.

HeaderBrushProperty static

public static readonly DependencyProperty HeaderBrushProperty

Identifies the HeaderBrush dependency property.

HolidaysProperty static

public static readonly DependencyProperty HolidaysProperty

Identifies the Holidays dependency property.

IsReadOnlyProperty static

public static readonly DependencyProperty IsReadOnlyProperty

Identifies the IsReadOnly dependency property.

LinkBrushProperty static

public static readonly DependencyProperty LinkBrushProperty

Identifies the LinkBrush dependency property.

LinksProperty static

public static readonly DependencyProperty LinksProperty

Identifies the Links dependency property.

NonWorkingBrushProperty static

public static readonly DependencyProperty NonWorkingBrushProperty

Identifies the NonWorkingBrush dependency property.

ProgressBrushProperty static

public static readonly DependencyProperty ProgressBrushProperty

Identifies the ProgressBrush dependency property.

ProjectStartProperty static

public static readonly DependencyProperty ProjectStartProperty

Identifies the ProjectStart dependency property.

RowHeightProperty static

public static readonly DependencyProperty RowHeightProperty

Identifies the RowHeight dependency property.

SelectedTaskProperty static

public static readonly DependencyProperty SelectedTaskProperty

Identifies the SelectedTask dependency property.

SelectionBrushProperty static

public static readonly DependencyProperty SelectionBrushProperty

Identifies the SelectionBrush dependency property.

ShowBaselinesProperty static

public static readonly DependencyProperty ShowBaselinesProperty

Identifies the ShowBaselines dependency property.

ShowCriticalPathProperty static

public static readonly DependencyProperty ShowCriticalPathProperty

Identifies the ShowCriticalPath dependency property.

ShowLinksProperty static

public static readonly DependencyProperty ShowLinksProperty

Identifies the ShowLinks dependency property.

ShowTodayProperty static

public static readonly DependencyProperty ShowTodayProperty

Identifies the ShowToday dependency property.

SummaryBrushProperty static

public static readonly DependencyProperty SummaryBrushProperty

Identifies the SummaryBrush dependency property.

TasksProperty static

public static readonly DependencyProperty TasksProperty

Identifies the Tasks dependency property.

TodayBrushProperty static

public static readonly DependencyProperty TodayBrushProperty

Identifies the TodayBrush dependency property.

TodayProperty static

public static readonly DependencyProperty TodayProperty

Identifies the Today dependency property.

WeekStartProperty static

public static readonly DependencyProperty WeekStartProperty

Identifies the WeekStart dependency property.

WorkingWeekProperty static

public static readonly DependencyProperty WorkingWeekProperty

Identifies the WorkingWeek dependency property.

ZoomProperty static

public static readonly DependencyProperty ZoomProperty

Identifies the Zoom dependency property.