🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
Creating CustomControl that Shows Data in a Gantt Chart
This page was created by Stephanie on 2023-06-22. Last edited by Wikiadmin on 2026-07-29.

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.

  1. Create a class for a Gantt row, such as WorkItem.
  2. Add attributes or derived values that will supply the two tree-grid values. For example, Name and Status.
  3. Add a recursive association from WorkItem to child WorkItem objects. This is the source for the ViewModel association named TreeNodes.
  4. Create a class for a dated item, such as ScheduleItem.
  5. Add DateTime attributes for its start and stop times, a string attribute for its label, and an integer attribute for its color.
  6. Associate each ScheduleItem with the WorkItem row 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.

  1. Add the Gantt custom-control override to the ViewModel UI.
  2. Verify that its tree binding is set to the list named TreeNodes.
  3. Verify that the row template uses Column1 and Column2.
  4. Verify that the Gantt-row binding uses TimeItems.
  5. Verify that the time-item template uses Start, Stop, Text, and Color.
  6. 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.

  1. Add an Action column named MoveToNewRow on the ViewModel item that represents a time item.
  2. Declare a ViewModel variable named vNewRow. Its type must be the class that represents a tree row, not the time-item class.
  3. 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 TreeNodes tree.
  • Column1 and Column2 display the expected row values.
  • A child row appears under its parent through the row-level TreeNodes association.
  • A time item with valid Start and Stop values appears on its row.
  • The item shows its Text and uses its Color value.
  • Moving an item selects or sets a destination in vNewRow and updates the destination row association through MoveToNewRow.

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.

See also