You can bind hierarchical, time-based data from a ViewModel to a WPF Gantt custom control when you build the ViewModel around the control's required list, column, and association names.
What you build
The Gantt control renders a tree on the left and time items on the right. Each tree row can display two text values and a collection of dated time items. Rows can contain child rows, so the hierarchy can continue to any depth.
For example, a project-plan Gantt can show:
| Tree row | Column1 | Column2 | Time item |
|---|---|---|---|
| Project Alpha | Alpha | Planning | Planning, 2026-01-05 to 2026-01-12 |
| Design | Design | In progress | Create mock-ups, 2026-01-13 to 2026-01-20 |
The control uses WPF data binding. It does not require your domain classes to be named TreeNode or TimeItem; those are the names it expects in the ViewModel contract.
Understand the binding contract
Create a ViewModel list named TreeNodes. Its items must expose the columns and associations in the following table.
| ViewModel element | Required name | Type or purpose |
|---|---|---|
| Root list column | TreeNodes
|
A list of the rows at the top of the Gantt tree. |
| Tree-row column | Column1
|
The first value displayed in the tree grid. |
| Tree-row column | Column2
|
The second value displayed in the tree grid. |
| Tree-row association | TimeItems
|
The time items rendered on this row. |
| Child-row association | TreeNodes
|
Child rows. Each child must expose the same row contract, including Column1, Column2, TimeItems, and its own TreeNodes association.
|
| Time-item column | Start
|
Start date and time (DateTime).
|
| Time-item column | Stop
|
End date and time (DateTime).
|
| Time-item column | Text
|
Text displayed for the time item (string).
|
| Time-item column | Color
|
Item color (int).
|
Names are significant. The wrapper binds to TreeNodes, TimeItems, Start, Stop, Text, and Color. A domain attribute named PlannedStart, for example, must be exposed in the ViewModel as a column named Start.
Prepare the model
Start with a model that can represent rows, hierarchy, and dated items. The class names below are examples; use names that fit your model.
- Create a class for a Gantt row, such as
WorkItem. - Add attributes or derived values that will supply the two tree-grid values. For example,
NameandStatus. - Add a recursive association from
WorkItemto childWorkItemobjects. This is the source for the ViewModel association namedTreeNodes. - Create a class for a dated item, such as
ScheduleItem. - Add
DateTimeattributes for its start and stop times, a string attribute for its label, and an integer attribute for its color. - Associate each
ScheduleItemwith theWorkItemrow that owns it.
A recursive row association is what lets the control show a project, its phases, and work items as expandable tree levels. The Gantt custom control can bind child rows repeatedly as long as each level follows the same contract.
Create the ViewModel data shape
Create a ViewModel that exposes the required names, mapping them to your model. The following mapping illustrates a project-plan model:
| Domain data | ViewModel contract name | Example |
|---|---|---|
List of top-level WorkItem objects
|
TreeNodes
|
Projects with no parent |
WorkItem.Name
|
Column1
|
Design
|
WorkItem.Status
|
Column2
|
In progress
|
Child WorkItem objects
|
TreeNodes
|
Tasks below Design |
WorkItem.ScheduleItems
|
TimeItems
|
Schedule items for Design |
ScheduleItem.PlannedStart
|
Start
|
2026-01-13 08:00 |
ScheduleItem.PlannedStop
|
Stop
|
2026-01-20 17:00 |
ScheduleItem.Caption
|
Text
|
Create mock-ups |
ScheduleItem.DisplayColor
|
Color
|
An integer color value |
Expose all data that the control needs in the ViewModel. If a value is needed for a binding but does not need to be edited in the ordinary ViewModel user interface, it can still be present as a column for the control.
Attach the Gantt UI override
Use the Gantt wrapper or UI override that is available in your solution, then connect it to the ViewModel that implements the contract.
- Add the Gantt custom-control override to the ViewModel UI.
- Verify that its tree binding is set to the list named
TreeNodes. - Verify that the row template uses
Column1andColumn2. - Verify that the Gantt-row binding uses
TimeItems. - Verify that the time-item template uses
Start,Stop,Text, andColor. - Run the ViewModel with at least one top-level row and one time item. Confirm that the row appears in the tree and its time item appears in the timeline.
When the names and types match, changes to the bound data are reflected through WPF data binding. This lets users work with tree text and time items in the Gantt UI.
Enable moving a time item to another row
To let a user move a time item from one Gantt row to another, provide an action on the time-item ViewModel item and a variable that identifies the destination row.
- Add an Action column named
MoveToNewRowon the ViewModel item that represents a time item. - Declare a ViewModel variable named
vNewRow. Its type must be the class that represents a tree row, not the time-item class. - In the action's execute expression, add the current time item to the destination row's time-item association.
For a model where the row class is WorkItem and its association to schedule items is named ScheduleItems, the action expression is:
vNewRow.ScheduleItems.add(self)Here, self is the time item on which the action runs. Replace ScheduleItems with the actual association-end name from your model. The ViewModel contract still calls the displayed association TimeItems; the action expression must use the association name that exists on the object held by vNewRow.
Test the finished control
Use this checklist before extending the control further:
- A top-level object appears in the
TreeNodestree. Column1andColumn2display the expected row values.- A child row appears under its parent through the row-level
TreeNodesassociation. - A time item with valid
StartandStopvalues appears on its row. - The item shows its
Textand uses itsColorvalue. - Moving an item selects or sets a destination in
vNewRowand updates the destination row association throughMoveToNewRow.
If rows appear but no bars appear, first check that TimeItems is exposed from the row and that every time item supplies DateTime values through the exact names Start and Stop. If bars appear but the tree is incomplete, check that every child level exposes the same TreeNodes contract.
Sample
For a downloadable interactive implementation, see the Gantt Chart Interactive example on Documentation:Complete model examples. The Documentation:Turnkey sample Board Map Balls Gantt page covers a separate Turnkey playground for HTML5 component development; it is not a replacement for this WPF binding contract.
