TaskBoard
A task board for Windows Forms: a plan's work as cards in workflow columns, optionally split into lanes by assignee, category or phase, moved by dragging or entirely from the keyboard.
public partial class TaskBoard : Control
Inherits from / implements: Control
Remarks
What it is for
Use it for the day-to-day running of a plan – stand-ups, triage, "what is everyone working
on?" – over the same tasks a GanttChart and a PertChart schedule. Moving
a card is changing the task, so the other charts see it at once.
Columns, lanes and cards
A column is a value of ProjectTask.Status: give the board its workflow in
Columns, or leave that empty and the statuses the tasks use become the columns, in
the order they first appear ("To do", "In progress" and "Done" when no task has a status). A task
whose status has no column is shown in the first column. A lane is a value of the field
LaneBy names – the assignee, the category, or the phase (top-level summary) a task
belongs to – and tasks with no value share a lane of their own.
Every task that is work, not a summary, is a card. A card shows the task's name, its scheduled
finish date, its assignee's initials and a bar for its progress; a milestone has a diamond before
its name, and while ShowCriticalPath is on a critical task has a stripe in
CriticalColor. Within a cell, cards are in ProjectTask.Rank order, then
in the order of Tasks. Each column heading shows how many cards it holds, against its
BoardColumn.Limit when it has one.
Moving cards
Dropping a card in another column sets its task's status; in another lane, the lane's field;
and the cards of the cell it lands in are given fresh ranks, so the order the reader made is kept.
Every move – a drag, a keyboard drop or MoveCard – is offered first through the
cancelable CardMoving event, is refused by a full column when
StrictLimits is on, and is announced by CardMoved once the task has
changed. ReadOnly stops the reader moving cards.
Keyboard
| Keys | Action |
|---|---|
Arrows | Move between cards: Up and Down through a column (running on into the next lane), Left and Right to the neighbouring column. |
Home, End | Go to the first and last card of the column. |
Page Up, Page Down | Scroll the lanes. |
Space | Pick the selected card up. The arrows then carry it – Shift with Up or Down to the next lane – and Space or Enter drops it, or Esc puts it back. |
Enter | Raise |
A card picked up is drawn travelling as the keys move it, and every step – picked up, where it would go, dropped or put back – is announced to screen readers. A card dragged near the edge of the board scrolls it. In a right-to-left layout the columns run from right to left, and so do the arrow keys.
Examples
A form's constructor that shows a board of the plan's work, a lane per person, with a review
step that can hold at most two cards and a rule that work reaches Done only through Review.
tasks and links are observable collections such as those built in the
GanttChart example; SaveTask is the application's own method.
using System.Windows.Forms;
using Binarymission.WinForms.Controls.ProjectManagement;
TaskBoard board = new TaskBoard
{
Dock = DockStyle.Fill,
Tasks = tasks,
Links = links,
LaneBy = BoardLaneBy.Assignee,
StrictLimits = true
};
board.Columns.Add(new BoardColumn("To do"));
board.Columns.Add(new BoardColumn("In progress", 3));
board.Columns.Add(new BoardColumn("Review", 2));
board.Columns.Add(new BoardColumn("Done"));
board.CardMoving += (sender, e) =>
{
if (e.ToStatus == "Done" && e.FromStatus != "Review")
e.Cancel = true;
};
// The task already has its new status, lane and rank.
board.CardMoved += (sender, e) => SaveTask(e.Task);
Controls.Add(board);See also
Members at a glance
| Constructors | |
|---|---|
TaskBoard | Creates an empty board: empty, watched Tasks, Links and
Holidays collections, no Columns (so the tasks' own statuses are the
columns), no lanes, on the system's window colours. |
| Properties | |
CardBackColor | Gets or sets the fill of a card. |
CardBorderColor | Gets or sets the border of a card. |
CardHeight | Gets or sets the height of a card. |
ColumnBackColor | Gets or sets the fill of a column, the band behind its cards that runs down every lane. |
ColumnWidth | Gets or sets the width of a column, and so of its cards. |
Columns | Gets the board's columns – its workflow – in the order they appear. |
CriticalColor | Gets or sets the colour of the stripe down the side of a card whose task is on the critical path. |
Holidays | Gets or sets the dates that are not worked, such as public holidays. |
LaneBy | Gets or sets what the board's rows – its lanes – are split by. |
Links | Gets or sets the dependencies between the tasks, which decide each card's finish date and whether it is on the critical path. |
OverLimitColor | Gets or sets the colour of the count of a column holding more cards than its
BoardColumn.Limit, and of the mark over its heading. |
ProgressColor | Gets or sets the colour of the thin bar along the bottom of a card that shows how far its task has got, and of a milestone's diamond. |
ProjectStart | Gets or sets the first day work can happen. No task is scheduled before it, except one that must start on an earlier date. |
ReadOnly | Gets or sets whether the reader is stopped from moving cards. |
SelectedTask | Gets or sets the task whose card is selected. |
ShowCriticalPath | Gets or sets whether a card whose task is on the critical path carries a stripe down its side in
CriticalColor. |
StrictLimits | Gets or sets whether a column that already holds as many cards as its BoardColumn.Limit
refuses another. |
Tasks | Gets or sets the tasks of the plan, as a flat list with parent references. Every task that is work, not a summary, is a card. |
Today | Gets or sets the date the charts treat as today. |
WorkingWeek | Gets or sets the days of the week that are worked. Durations and lags count only these days. |
| Methods | |
CreateAccessibilityInstance | Creates the accessible object that presents the board to screen readers and other assistive technology as a list: each column heading, saying its count and limit, followed by its cards in reading order. |
Dispose | Stops watching the plan and releases the fonts, the timer and the tooltip the board created. |
EnsureSchedule | Gets the plan as the board has scheduled it: every task's dates and float, the critical path, and anything in the plan that could not be used. |
IsInputKey | Claims the keys the board uses for itself, so that the form does not take them for moving the focus or pressing a button. |
MoveCard | Moves a card as though the reader had dropped it: to a column, optionally to another lane, at a position in that cell. |
OnCardMoved | Raises the CardMoved event. |
OnCardMoving | Raises the CardMoving event. |
OnDpiChangedAfterParent | Rebuilds everything measured in device pixels when the board moves to a display with a different scale: the fonts, the scroll bars and the scroll range. |
OnFontChanged | Raises Control.FontChanged and rebuilds the fonts the cards are written in. |
OnGotFocus | Draws the focus cue and announces the selected card to screen readers. |
OnHandleCreated | Fits the scroll bars once the window exists and the display's scale is known for certain, and schedules any changes made before then. |
OnHandleDestroyed | Forgets a refresh posted to a window that is going away; the next window posts again. |
OnKeyDown | Raises Control.KeyDown, then, unless a handler has handled the key, carries out the
board's keyboard commands: the arrows move between cards, Space picks the selected card up, Enter
raises TaskActivated; while a card is carried, the arrows move it (Shift with Up or
Down to the next lane), Space or Enter drops it and Esc puts it back. |
OnLostFocus | Puts back a card that is being carried – the keys that would drop it are going elsewhere – and removes the focus cue. |
OnMouseCaptureChanged | Puts a dragged card back when the mouse is taken away part way through, by a message box or a switch of window. |
OnMouseDoubleClick | Raises Control.MouseDoubleClick, then raises TaskActivated when the
double-click was on a card. |
OnMouseDown | Raises Control.MouseDown, takes the focus, and with the left button selects the card
under the pointer, ready to drag it once the pointer moves far enough. A press while a card is
carried from the keyboard puts that card back. |
OnMouseLeave | Raises Control.MouseLeave and hides the tooltip. |
OnMouseMove | Raises Control.MouseMove, then carries a dragged card, showing where it would land;
otherwise shows the tooltip for the card under the pointer. |
OnMouseUp | Raises Control.MouseUp, then drops a dragged card, offering the move through
CardMoving. |
OnMouseWheel | Raises Control.MouseWheel, then scrolls the lanes up and down, or sideways with
Shift. A card being dragged follows the pointer as the board scrolls. |
OnPaint | Raises Control.Paint, then draws the column bands, the lanes, the cards, a card being
moved and the header row. A fault while drawing is absorbed rather than leaving the control crossed
out, and the next paint tries again. |
OnResize | Raises Control.Resize and fits the scroll bars and the view to the new size. |
OnRightToLeftChanged | Raises Control.RightToLeftChanged and lays the board out again mirrored, with the
first column on the right, scrolled to it. |
OnScheduleChanged | Raises the ScheduleChanged event. |
OnSelectedTaskChanged | Raises the SelectedTaskChanged event. |
OnTaskActivated | Raises the TaskActivated event. |
Reschedule | Schedules the plan and lays the board out again now, and raises ScheduleChanged. |
ScrollToTask | Scrolls the board until a task's card is in view. |
| Events | |
CardMoved | Occurs after a card has moved and its task's status, lane field and rank have been written: the moment to save the task. |
CardMoving | Occurs before a card moves – by a drag, a keyboard drop or MoveCard – so that the
application can refuse the move. |
ScheduleChanged | Occurs after the plan has been scheduled again because something changed: a task, a link, a
collection, a calendar setting, or a call to Reschedule. |
SelectedTaskChanged | Occurs when the selected card changes: by the reader, by setting SelectedTask, or
because the selected task left the board. |
TaskActivated | Occurs when the reader double-clicks a card or presses Enter with a card selected: the moment to open the application's own view of the task. |
Constructors
TaskBoard
Properties
CardBackColor
Gets or sets the fill of a card.
- Value
- The default is
Color.Empty, which usesControl.BackColor. - Designer category
- Appearance
Remarks
In Windows high-contrast mode the system colours are used instead.
CardBorderColor
Gets or sets the border of a card.
- Value
- The default is
Color.Empty, a shade betweenControl.BackColorandControl.ForeColor. - Designer category
- Appearance
Remarks
In Windows high-contrast mode the system colours are used instead.
CardHeight
Gets or sets the height of a card.
- Value
- In logical pixels (1/96 inch), scaled with the display. The default is 76; a smaller value than 48 is raised to 48.
- Default
DefaultCardHeight- Designer category
- Layout
Remarks
A card shows up to two lines of its task's name; a taller card leaves more room around them but no more lines.
ColumnBackColor
Gets or sets the fill of a column, the band behind its cards that runs down every lane.
- Value
- The default is
Color.Empty, a faint shade ofControl.ForeColoroverControl.BackColor. - Designer category
- Appearance
Remarks
In Windows high-contrast mode the system colours are used instead.
ColumnWidth
Gets or sets the width of a column, and so of its cards.
- Value
- In logical pixels (1/96 inch), scaled with the display. The default is 260; a smaller value than 180 is raised to 180.
- Default
DefaultColumnWidth- Designer category
- Layout
Columns
Gets the board's columns – its workflow – in the order they appear.
- Value
- Never
null. Empty by default, in which case the statuses the tasks use are the columns, in the order they first appear, and "To do", "In progress" and "Done" when no task has a status.
Remarks
Adding, removing or replacing a column redraws the board at once. A column's own properties are
plain values: after changing one in place, call Reschedule. Columns with no
BoardColumn.Status, and any after the first with the same status, are ignored.
A task whose status matches no column is shown in the first column, so that no card is ever off the board; moving it sets its status to the column it is dropped in.
Example
board.Columns.Add(new BoardColumn("Backlog"));
board.Columns.Add(new BoardColumn("Doing", 4));
board.Columns.Add(new BoardColumn("Done"));CriticalColor
Gets or sets the colour of the stripe down the side of a card whose task is on the critical path.
- Value
- The default is a red-orange, RGB 224, 82, 43.
- Designer category
- Appearance
Remarks
Used only while ShowCriticalPath is on. Setting Color.Empty returns
to the default. In Windows high-contrast mode the system colours are used
instead.
Holidays
Gets or sets the dates that are not worked, such as public holidays.
- Value
- Dates; only their date part is read. Never
null: the board starts with an emptyObservableCollection, and settingnullgives a new empty one.
Remarks
Durations and lags skip these dates, which moves the finish dates on the cards. An
observable collection is watched; after changing a plain list, call
Reschedule.
LaneBy
Gets or sets what the board's rows – its lanes – are split by.
- Value
- The default is
BoardLaneBy.None: one lane, so the board is just columns. - Default
BoardLaneBy.None- Designer category
- Plan
Remarks
Lanes are made from the values the tasks have: a lane per assignee or category in the order
they first appear, or a lane per phase in plan order. Tasks with no value share a lane, placed last
and labelled "Unassigned", "Uncategorised" or "No phase". Dropping a card in another lane sets the
task's ProjectTask.Assignee, ProjectTask.Category or
ProjectTask.ParentId.
Changing it puts back a card that is being carried.
Links
Gets or sets the dependencies between the tasks, which decide each card's finish date and whether it is on the critical path.
- Value
- The links. Never
null: the board starts with an emptyObservableCollection, and settingnullgives a new empty one.
Remarks
Watched in the same way as Tasks. The board never changes the list.
OverLimitColor
Gets or sets the colour of the count of a column holding more cards than its
BoardColumn.Limit, and of the mark over its heading.
- Value
- The default is a plain red, RGB 201, 42, 42.
- Designer category
- Appearance
Remarks
Setting Color.Empty returns to the default. In Windows high-contrast
mode the system colours are used instead.
ProgressColor
Gets or sets the colour of the thin bar along the bottom of a card that shows how far its task has got, and of a milestone's diamond.
- Value
- The default is a calm blue, RGB 59, 125, 216.
- Designer category
- Appearance
Remarks
Setting Color.Empty returns to the default. In Windows high-contrast mode
the system colours are used instead.
ProjectStart
Gets or sets the first day work can happen. No task is scheduled before it, except one that must start on an earlier date.
- Value
- A date; only its date part is kept, and a day that is not worked is moved to the next working
day. The default is
null, which takes the earliest plannedProjectTask.Startin the plan, then the earliest plannedProjectTask.Finish, and failing both, today's date. - Default
null- Designer category
- Plan
Remarks
Give every chart showing a plan the same value, so that they schedule the same dates.
ReadOnly
Gets or sets whether the reader is stopped from moving cards.
- Value
trueto stop the reader moving cards. The default isfalse.- Default
false- Designer category
- Behavior
Remarks
Selecting, navigating and TaskActivated still work, and so does
MoveCard, which is the application's own call. Turning it on puts back a card that is
being carried.
SelectedTask
Gets or sets the task whose card is selected.
- Value
- A task in
Tasks, ornull(the default) when no card is selected.
Remarks
Setting a task scrolls its card into view, and raises SelectedTaskChanged when
the selection changes. Setting a task that has no card – a summary, or a task not in the plan –
clears the selection. When the selected task leaves the board, the selection is cleared and
SelectedTaskChanged is raised from the message loop.
ShowCriticalPath
Gets or sets whether a card whose task is on the critical path carries a stripe down its side in
CriticalColor.
- Value
true(the default) to mark critical cards.- Default
true- Designer category
- Appearance
StrictLimits
Gets or sets whether a column that already holds as many cards as its BoardColumn.Limit
refuses another.
- Value
trueto refuse the move. The default isfalse: a column may go past its limit, and its count is then shown inOverLimitColor.- Default
false- Designer category
- Behavior
Remarks
It applies to moves into a column from another one, by the reader and by
MoveCard alike; reordering cards within a column is always allowed. A card carried over
a full column is drawn as refused, and dropping it there puts it back.
Tasks
Gets or sets the tasks of the plan, as a flat list with parent references. Every task that is work, not a summary, is a card.
- Value
- The tasks. Never
null: the board starts with an emptyObservableCollection, and settingnullgives a new empty one.
Remarks
An ObservableCollection or a
BindingList is watched, and so is every task in it. A plain
list is read when it is assigned; call Reschedule after changing one. The order of the
list is the order of cards that have no ProjectTask.Rank. Setting a new list scrolls
back to the first column.
Today
Gets or sets the date the charts treat as today.
- Value
- A date; only its date part is kept. The default is
null, the computer's date. - Default
null- Designer category
- Plan
Remarks
The Gantt chart draws its today line from this. A board has no time axis, so it draws nothing from it, and changing it does not redraw the board; it is here so that one set of plan settings can be given to all three charts alike.
WorkingWeek
Gets or sets the days of the week that are worked. Durations and lags count only these days.
- Value
- A combination of
WorkingWeekflags. The default isWorkingWeek.Weekdays, Monday to Friday;WorkingWeek.Noneis read as every day being worked. - Default
WorkingWeek.Weekdays- Designer category
- Plan
Methods
CreateAccessibilityInstance
Creates the accessible object that presents the board to screen readers and other assistive technology as a list: each column heading, saying its count and limit, followed by its cards in reading order.
Returns
The board's accessible object.
Dispose
Stops watching the plan and releases the fonts, the timer and the tooltip the board created.
Parameters
disposingtruewhen called fromDispose;falsefrom the finaliser.
Remarks
The application's tasks, links and holidays are not touched: they can be given to another chart.
EnsureSchedule
Gets the plan as the board has scheduled it: every task's dates and float, the critical path, and anything in the plan that could not be used.
- Value
- Never
null.
Remarks
Scheduled again first when anything has changed. The board reads each card's finish date and critical mark from it. The schedule returned is a snapshot; read the property again after a change.
IsInputKey
Claims the keys the board uses for itself, so that the form does not take them for moving the focus or pressing a button.
Parameters
keyData- The key, with its modifiers.
Returns
true for the arrows, Home, End, Page Up and Page Down; for Enter without
modifiers while a card is selected or carried; and for Esc while a card is carried – so that a
dialog's default and cancel buttons keep those keys otherwise. Otherwise what the base class
answers.
MoveCard
Moves a card as though the reader had dropped it: to a column, optionally to another lane, at a position in that cell.
Parameters
task- The task whose card moves.
status- The column to move it to: the
BoardColumn.Statusof a column on the board. lane- The lane to move it to: an assignee or a category, or a phase's task id when
LaneByisBoardLaneBy.Parent; empty for the lane of tasks without a value;nullto keep the card's lane. Ignored when the board has no lanes. A value no card has yet makes a new lane, except for phases, where it must be a phase on the board. index- The card's position in the cell, from 0; a value past either end puts it at that end.
Returns
true when the card moved; false when the move was refused
by StrictLimits, cancelled in CardMoving, would change nothing, or named a
task or column that is not on the board.
Remarks
The move follows the same path as the reader's: refused by a full column when
StrictLimits is on, offered through CardMoving with a
CardMovingEventArgs.Source of TaskEditSource.Application, written to the
task, and announced by CardMoved. It works even when ReadOnly is set,
which only stops the reader.
Example
// A build server reports that the API is deployed: move its card to the top of Review.
ProjectTask api = tasks.First(task => task.Id == "api");
if (!board.MoveCard(api, "Review", null, 0))
{
statusLabel.Text = "Review is full - the API card stays where it is.";
}OnCardMoved
Raises the CardMoved event.
Parameters
e- The task whose card moved.
Remarks
A derived board that overrides this should call the base method, or the event is not raised.
OnCardMoving
Raises the CardMoving event.
Parameters
e- The proposed move. Set its
CancelEventArgs.Cancelto refuse it.
Remarks
The board reads CancelEventArgs.Cancel after this returns. A derived board can refuse a move here, before or instead of calling the base method.
OnDpiChangedAfterParent
Rebuilds everything measured in device pixels when the board moves to a display with a different scale: the fonts, the scroll bars and the scroll range.
Parameters
e- Empty event data.
OnFontChanged
Raises Control.FontChanged and rebuilds the fonts the cards are written in.
Parameters
e- Empty event data.
OnGotFocus
Draws the focus cue and announces the selected card to screen readers.
Parameters
e- Empty event data.
OnHandleCreated
Fits the scroll bars once the window exists and the display's scale is known for certain, and schedules any changes made before then.
Parameters
e- Empty event data.
OnHandleDestroyed
Forgets a refresh posted to a window that is going away; the next window posts again.
Parameters
e- Empty event data.
OnKeyDown
Raises Control.KeyDown, then, unless a handler has handled the key, carries out the
board's keyboard commands: the arrows move between cards, Space picks the selected card up, Enter
raises TaskActivated; while a card is carried, the arrows move it (Shift with Up or
Down to the next lane), Space or Enter drops it and Esc puts it back.
Parameters
e- The key and its modifiers. Set as handled when the board acts on it.
OnLostFocus
Puts back a card that is being carried – the keys that would drop it are going elsewhere – and removes the focus cue.
Parameters
e- Empty event data.
OnMouseCaptureChanged
Puts a dragged card back when the mouse is taken away part way through, by a message box or a switch of window.
Parameters
e- Empty event data.
OnMouseDoubleClick
Raises Control.MouseDoubleClick, then raises TaskActivated when the
double-click was on a card.
Parameters
e- The button, position and click count.
OnMouseDown
Raises Control.MouseDown, takes the focus, and with the left button selects the card
under the pointer, ready to drag it once the pointer moves far enough. A press while a card is
carried from the keyboard puts that card back.
Parameters
e- The button, position and click count.
OnMouseLeave
Raises Control.MouseLeave and hides the tooltip.
Parameters
e- Empty event data.
OnMouseMove
Raises Control.MouseMove, then carries a dragged card, showing where it would land;
otherwise shows the tooltip for the card under the pointer.
Parameters
e- The button, position and click count.
OnMouseUp
Raises Control.MouseUp, then drops a dragged card, offering the move through
CardMoving.
Parameters
e- The button, position and click count.
OnMouseWheel
Raises Control.MouseWheel, then scrolls the lanes up and down, or sideways with
Shift. A card being dragged follows the pointer as the board scrolls.
Parameters
e- The wheel's movement and the pointer's position.
OnPaint
Raises Control.Paint, then draws the column bands, the lanes, the cards, a card being
moved and the header row. A fault while drawing is absorbed rather than leaving the control crossed
out, and the next paint tries again.
Parameters
e- The graphics to draw with and the area to draw.
OnResize
Raises Control.Resize and fits the scroll bars and the view to the new size.
Parameters
e- Empty event data.
OnRightToLeftChanged
Raises Control.RightToLeftChanged and lays the board out again mirrored, with the
first column on the right, scrolled to it.
Parameters
e- Empty event data.
OnScheduleChanged
Raises the ScheduleChanged event.
Parameters
e- Empty event data.
Remarks
A derived board that overrides this should call the base method, or the event is not raised.
OnSelectedTaskChanged
Raises the SelectedTaskChanged event.
Parameters
e- Empty event data.
Remarks
A derived board that overrides this should call the base method, or the event is not raised.
OnTaskActivated
Raises the TaskActivated event.
Parameters
e- The task that was activated.
Remarks
A derived board that overrides this should call the base method, or the event is not raised.
Reschedule
Schedules the plan and lays the board out again now, and raises ScheduleChanged.
Remarks
Needed only after changing a plain list given to Tasks, Links or
Holidays, which the board cannot watch, or after changing a
BoardColumn's properties in place.
ScrollToTask
Scrolls the board until a task's card is in view.
Parameters
task- The task to show. Nothing happens for
nullor a task that has no card.
Remarks
The selection is left as it is; set SelectedTask to select the task as well,
which scrolls to it too.
Events
CardMoved
Occurs after a card has moved and its task's status, lane field and rank have been written: the moment to save the task.
- Designer category
- Action
Remarks
The ranks of the other cards in the cell it landed in may have changed too.
CardMoving
Occurs before a card moves – by a drag, a keyboard drop or MoveCard – so that the
application can refuse the move.
- Designer category
- Action
Remarks
Set CancelEventArgs.Cancel to true to refuse it: the card goes
back where it was and nothing is written. A move into a full column while StrictLimits
is on is refused before this event, and a drop where the card already is raises nothing.
See also
ScheduleChanged
Occurs after the plan has been scheduled again because something changed: a task, a link, a
collection, a calendar setting, or a call to Reschedule.
- Designer category
- Behavior
Remarks
Raised from the message loop, once for any number of changes made together – moving one card can re-rank a whole column – and never from inside a paint, so a handler is free to change the plan again. Not raised for the board's first schedule.
SelectedTaskChanged
Occurs when the selected card changes: by the reader, by setting SelectedTask, or
because the selected task left the board.
- Designer category
- Behavior
TaskActivated
Occurs when the reader double-clicks a card or presses Enter with a card selected: the moment to open the application's own view of the task.
- Designer category
- Action