Blazorise Gantt component

Build timeline-driven planning experiences with a synchronized tree and timeline view.

The Gantt component is designed for project planning use cases where tasks have hierarchy, dates, duration, and progress. It supports declarative columns, built-in editing, keyboard and mouse interactions, and template-based customization.

To use the Gantt component, install the Blazorise.Gantt package first.

Installation

NuGet

Install extension from NuGet.
Install-Package Blazorise.Gantt

Imports

In your main _Imports.razor add:
@using Blazorise.Gantt

Fundamentals

Data Model

Gantt<TItem> binds to your own model type through field mapping parameters such as IdField, StartField, and EndField. You can keep your existing model names and map them without creating a dedicated DTO.

Must-Have Fields

For most production scenarios, these are the fields you should map:

  • StartField and EndField: Required to render timeline bars. If either value is missing/unassigned, the item cannot be drawn on the timeline.
  • TitleField: Recommended for readable tree rows and task labels.
  • IdField: Strongly recommended for stable identity, selection/state behavior, and CRUD operations.
  • DurationField (optional): Used for duration column/editing. If not mapped, duration is calculated from StartField and EndField.
  • ProgressField (optional): Enables progress percentage in bars, columns, and the edit dialog slider.

Flat vs Hierarchical Data

Gantt supports both data shapes:

  • Flat data: One collection with IdField and ParentIdField. This is usually best for API-driven data.
  • Hierarchical data: Nested child collections mapped through ItemsField.
  • If both ParentIdField and ItemsField exist, Gantt uses flat mode by default. Set HierarchicalData="true" to force hierarchical mode.
  • If ItemsField exists and ParentIdField does not, hierarchical mode is used automatically.

Columns

Use GanttColumns and declarative column components to control field mapping, order, visibility, sorting, alignment, and templates. This keeps tree rendering explicit and easy to evolve as requirements grow.

Editing and Commands

Set Editable to enable built-in create, add-child, edit, and delete flows. Use command switches and CommandAllowed for role-based or item-based command rules.

Set UseInternalEditing="false" when you want Gantt to keep its command affordances but let your page own the modal and persistence flow through NewItemClicked, AddChildItemClicked, EditItemClicked, and DeleteItemClicked.

Examples

Flat Data Binding

Use the classic Id + ParentId model when your API already returns a flat task list.

Some columns are hidden by default so the timeline has more space; use the Column Picker in the toolbar to show them.

Mar 16 - Mar 22, 2026
Task
Start
Website redesign
Mar 18, 2026
Discovery
Mar 18, 2026
Implementation
Mar 22, 2026
Components
Mar 23, 2026
Accessibility pass
Mar 28, 2026
Launch
Apr 01, 2026
Mon 16
Tue 17
Wed 18
Thu 19
Fri 20
Sat 21
Sun 22
Website redesign
Discovery
Implementation
<Gantt TItem="TaskItem"
       Data="@tasks"
       Date="@selectedDate"
       SelectedView="GanttView.Week"
       DurationField="Duration">
    <GanttColumns>
        <GanttColumn Field="Title" Title="Task" Expandable Width="Width.Px(220)" />
        <GanttColumn Field="Start" Width="Width.Px(130)" />
        <GanttColumn Field="End" Width="Width.Px(130)" Visible="false" />
        <GanttColumn Field="Duration" Width="Width.Px(90)" TextAlignment="TextAlignment.Center" Visible="false" />
    </GanttColumns>
    <GanttToolbar />
    <GanttViews>
        <GanttWeekView TimelineCellWidth="90" RowHeight="44" />
    </GanttViews>
</Gantt>
@code {
    private DateOnly selectedDate = DateOnly.FromDateTime( DateTime.Today );

    private List<TaskItem> tasks = CreateTasks();

    private static List<TaskItem> CreateTasks()
    {
        var baseDate = DateTime.Today.AddDays( -2 );

        var result = new List<TaskItem>
        {
            new() { Id = "1", Title = "Website redesign", Start = baseDate, End = baseDate.AddDays( 16 ) },
            new() { Id = "2", ParentId = "1", Title = "Discovery", Start = baseDate, End = baseDate.AddDays( 4 ) },
            new() { Id = "3", ParentId = "1", Title = "Implementation", Start = baseDate.AddDays( 4 ), End = baseDate.AddDays( 14 ) },
            new() { Id = "4", ParentId = "3", Title = "Components", Start = baseDate.AddDays( 5 ), End = baseDate.AddDays( 10 ) },
            new() { Id = "5", ParentId = "3", Title = "Accessibility pass", Start = baseDate.AddDays( 10 ), End = baseDate.AddDays( 13 ) },
            new() { Id = "6", ParentId = "1", Title = "Launch", Start = baseDate.AddDays( 14 ), End = baseDate.AddDays( 16 ) },
        };

        foreach ( var item in result )
        {
            item.Duration = Math.Max( 1, (int)Math.Ceiling( ( item.End - item.Start ).TotalDays ) );
        }

        return result;
    }

    public class TaskItem
    {
        public string Id { get; set; }

        public string ParentId { get; set; }

        public string Title { get; set; }

        public DateTime Start { get; set; }

        public DateTime End { get; set; }

        public int Duration { get; set; }
    }
}

Hierarchical Data Binding

Bind directly to nested task collections with ItemsField for tree-shaped data models.
Mar 16 - Mar 22, 2026
WBS
Task
Start
1
Mobile app release
Mar 18, 2026
1.1
Planning
Mar 18, 2026
1.2
Execution
Mar 22, 2026
1.2.1
API integration
Mar 23, 2026
1.2.2
QA
Mar 29, 2026
1.3
Go-live
Apr 03, 2026
Mon 16
Tue 17
Wed 18
Thu 19
Fri 20
Sat 21
Sun 22
Mobile app release
Planning
Execution
<Gantt TItem="TaskItem"
       Data="@tasks"
       Date="@selectedDate"
       SelectedView="GanttView.Week"
       ItemsField="Children"
       HierarchicalData
       DurationField="Duration">
    <GanttColumns>
        <GanttColumn Field="Wbs" Width="Width.Px(76)" TextAlignment="TextAlignment.Center" Visible="false" />
        <GanttColumn Field="Title" Title="Task" Expandable Width="Width.Px(220)" />
        <GanttColumn Field="Start" Width="Width.Px(130)" />
        <GanttColumn Field="End" Width="Width.Px(130)" Visible="false" />
        <GanttColumn Field="Duration" Width="Width.Px(90)" TextAlignment="TextAlignment.Center" Visible="false" />
    </GanttColumns>
    <GanttToolbar />
    <GanttViews>
        <GanttWeekView TimelineCellWidth="90" RowHeight="44" />
    </GanttViews>
</Gantt>
@code {
    private DateOnly selectedDate = DateOnly.FromDateTime( DateTime.Today );

    private List<TaskItem> tasks = CreateTasks();

    private static List<TaskItem> CreateTasks()
    {
        var baseDate = DateTime.Today.AddDays( -2 );

        var result = new List<TaskItem>
        {
            new()
            {
                Id = "1",
                Title = "Mobile app release",
                Start = baseDate,
                End = baseDate.AddDays( 18 ),
                Children = new()
                {
                    new()
                    {
                        Id = "2",
                        Title = "Planning",
                        Start = baseDate,
                        End = baseDate.AddDays( 4 ),
                    },
                    new()
                    {
                        Id = "3",
                        Title = "Execution",
                        Start = baseDate.AddDays( 4 ),
                        End = baseDate.AddDays( 16 ),
                        Children = new()
                        {
                            new()
                            {
                                Id = "4",
                                Title = "API integration",
                                Start = baseDate.AddDays( 5 ),
                                End = baseDate.AddDays( 11 ),
                            },
                            new()
                            {
                                Id = "5",
                                Title = "QA",
                                Start = baseDate.AddDays( 11 ),
                                End = baseDate.AddDays( 16 ),
                            },
                        },
                    },
                    new()
                    {
                        Id = "6",
                        Title = "Go-live",
                        Start = baseDate.AddDays( 16 ),
                        End = baseDate.AddDays( 18 ),
                    },
                },
            },
        };

        UpdateDuration( result );

        return result;
    }

    private static void UpdateDuration( IEnumerable<TaskItem> items )
    {
        foreach ( var item in items )
        {
            item.Duration = Math.Max( 1, (int)Math.Ceiling( ( item.End - item.Start ).TotalDays ) );
            UpdateDuration( item.Children );
        }
    }

    public class TaskItem
    {
        public string Id { get; set; }

        public string Title { get; set; }

        public DateTime Start { get; set; }

        public DateTime End { get; set; }

        public int Duration { get; set; }

        public List<TaskItem> Children { get; set; } = new();
    }
}

Built-in Editing

Enable Editable to use built-in create, add-child, update, and delete workflows. This example also demonstrates command-level control through CommandAllowed.
Mar 16 - Mar 22, 2026
Task
Start
Marketing campaign
Mar 18, 2026
Research
Mar 18, 2026
Creative
Mar 22, 2026
Distribution
Mar 27, 2026
Mon 16
Tue 17
Wed 18
Thu 19
Fri 20
Sat 21
Sun 22
Marketing campaign45%
Research100%
Creative70%
<Gantt TItem="TaskItem"
       Data="@tasks"
       Date="@selectedDate"
       SelectedView="GanttView.Week"
       DurationField="Duration"
       Editable
       CommandAllowed="@AllowCommand">
    <GanttColumns>
        <GanttColumn Field="Title" Title="Task" Expandable Width="Width.Px(230)" />
        <GanttColumn Field="Start" Width="Width.Px(130)" />
        <GanttColumn Field="End" Width="Width.Px(130)" Visible="false" />
        <GanttColumn Field="Duration" Width="Width.Px(90)" TextAlignment="TextAlignment.Center" Visible="false" />
        <GanttColumn Field="Progress" Width="Width.Px(96)" TextAlignment="TextAlignment.Center" Visible="false" />
        <GanttCommandColumn Width="Width.Px(60)" />
    </GanttColumns>
    <GanttToolbar />
    <GanttViews>
        <GanttWeekView TimelineCellWidth="90" RowHeight="44" />
    </GanttViews>
</Gantt>
@code {
    private DateOnly selectedDate = DateOnly.FromDateTime( DateTime.Today );

    private List<TaskItem> tasks = CreateTasks();

    private static List<TaskItem> CreateTasks()
    {
        var baseDate = DateTime.Today.AddDays( -2 );

        var result = new List<TaskItem>
        {
            new() { Id = "1", Title = "Marketing campaign", Start = baseDate, End = baseDate.AddDays( 15 ), Progress = 45d },
            new() { Id = "2", ParentId = "1", Title = "Research", Start = baseDate, End = baseDate.AddDays( 4 ), Progress = 100d },
            new() { Id = "3", ParentId = "1", Title = "Creative", Start = baseDate.AddDays( 4 ), End = baseDate.AddDays( 9 ), Progress = 70d },
            new() { Id = "4", ParentId = "1", Title = "Distribution", Start = baseDate.AddDays( 9 ), End = baseDate.AddDays( 15 ), Progress = 20d },
        };

        foreach ( var item in result )
        {
            item.Duration = Math.Max( 1, (int)Math.Ceiling( ( item.End - item.Start ).TotalDays ) );
        }

        return result;
    }

    private bool AllowCommand( GanttCommandContext<TaskItem> context )
    {
        if ( context.CommandType == GanttCommandType.Delete && context.Item?.ParentId is null )
            return false;

        return true;
    }

    public class TaskItem
    {
        public string Id { get; set; }

        public string ParentId { get; set; }

        public string Title { get; set; }

        public DateTime Start { get; set; }

        public DateTime End { get; set; }

        public int Duration { get; set; }

        public double Progress { get; set; }
    }
}

External Editing

By setting the UseInternalEditing=false Gantt raises command callbacks with the relevant item and context, but leaves the editing UI and persistence flow to your implementation. This is ideal for keeping Gantt as a pure view component while owning the user experience and data flow of your app.
Task
Start
Website redesign
Mar 18, 2026
Discovery
Mar 18, 2026
Implementation
Mar 22, 2026
Launch
Mar 30, 2026
Mon 16
Tue 17
Wed 18
Thu 19
Fri 20
Sat 21
Sun 22
Website redesign
Discovery
Implementation

Last external action: None

<Gantt TItem="TaskItem"
       Data="@tasks"
       Date="@selectedDate"
       SelectedView="GanttView.Week"
       DurationField="Duration"
       Editable
       UseInternalEditing="false"
       NewItemClicked="@OnNewItemClicked"
       AddChildItemClicked="@OnAddChildItemClicked"
       EditItemClicked="@OnEditItemClicked"
       DeleteItemClicked="@OnDeleteItemClicked">
    <GanttColumns>
        <GanttColumn Field="Title" Title="Task" Expandable Width="Width.Px( 230 )" />
        <GanttColumn Field="Start" Width="Width.Px( 130 )" />
        <GanttColumn Field="End" Width="Width.Px( 130 )" Visible="false" />
        <GanttColumn Field="Duration" Width="Width.Px( 90 )" TextAlignment="TextAlignment.Center" Visible="false" />
        <GanttCommandColumn Width="Width.Px( 176 )">
            <HeaderTemplate>
                @if ( context.CanAddTask )
                {
                    <Button Size="Size.ExtraSmall" Color="Color.Success" Outline Clicked="@context.AddTask">New</Button>
                }
            </HeaderTemplate>
            <DisplayTemplate>
                @if ( context.CanAddChild )
                {
                    <Button Size="Size.ExtraSmall" Color="Color.Secondary" Outline Margin="Margin.Is1.FromEnd" Clicked="@context.AddChild">Child</Button>
                }
                @if ( context.CanEdit )
                {
                    <Button Size="Size.ExtraSmall" Color="Color.Primary" Outline Margin="Margin.Is1.FromEnd" Clicked="@context.Edit">Edit</Button>
                }
                @if ( context.CanDelete )
                {
                    <Button Size="Size.ExtraSmall" Color="Color.Danger" Outline Clicked="@context.Delete">Delete</Button>
                }
            </DisplayTemplate>
        </GanttCommandColumn>
    </GanttColumns>
    <GanttViews>
        <GanttWeekView TimelineCellWidth="90" RowHeight="44" />
    </GanttViews>
</Gantt>

<Paragraph TextColor="TextColor.Muted" Margin="Margin.Is3.FromTop">
    Last external action: @lastAction
</Paragraph>

<Modal @bind-Visible="@editorVisible" Centered>
    <ModalContent>
        <ModalHeader>
            <ModalTitle>@editorModeTitle</ModalTitle>
            <CloseButton Clicked="@CloseEditor" />
        </ModalHeader>
        <ModalBody>
            <Paragraph TextColor="TextColor.Muted">
                This modal is owned by the page. Gantt only raises the command callbacks.
            </Paragraph>
            <Field>
                <FieldLabel>Title</FieldLabel>
                <FieldBody>
                    <TextInput @bind-Value="@editorTitle" Immediate="false" Placeholder="Task title" />
                </FieldBody>
            </Field>
        </ModalBody>
        <ModalFooter>
            <Button Color="Color.Secondary" Clicked="@CloseEditor">Cancel</Button>
            <Button Color="Color.Primary" Clicked="@SaveEditor">Save</Button>
        </ModalFooter>
    </ModalContent>
</Modal>
@code {
    private DateOnly selectedDate = DateOnly.FromDateTime( DateTime.Today );
    private List<TaskItem> tasks = CreateTasks();
    private bool editorVisible;
    private string editorModeTitle = "Edit task";
    private string editorTitle;
    private string editorParentId;
    private string editorTargetId;
    private TaskItem editorDraft;
    private string lastAction = "None";
    private int nextId = 100;

    private Task OnNewItemClicked( GanttCommandContext<TaskItem> context )
        => OpenEditor( context.Item, null, null, "Create task" );

    private Task OnAddChildItemClicked( GanttCommandContext<TaskItem> context )
        => OpenEditor( context.Item, context.ParentItem, null, $"Create child for {context.ParentItem?.Title}" );

    private Task OnEditItemClicked( GanttItemClickedEventArgs<TaskItem> context )
        => OpenEditor( context.Item, null, context.Item?.Id, $"Edit {context.Item?.Title}" );

    private Task OnDeleteItemClicked( GanttItemClickedEventArgs<TaskItem> context )
    {
        if ( context?.Item?.Id is null )
            return Task.CompletedTask;

        RemoveTaskWithChildren( tasks, context.Item.Id );
        lastAction = $"Deleted {context.Item.Title}";

        return Task.CompletedTask;
    }

    private Task OpenEditor( TaskItem item, TaskItem parentItem, string targetId, string modeTitle )
    {
        editorDraft = item?.Clone() ?? new TaskItem();
        editorParentId = parentItem?.Id;
        editorTargetId = targetId;
        editorTitle = editorDraft.Title ?? string.Empty;
        editorModeTitle = modeTitle;
        editorVisible = true;

        return Task.CompletedTask;
    }

    private Task CloseEditor()
    {
        editorVisible = false;
        editorDraft = null;
        editorParentId = null;
        editorTargetId = null;
        editorTitle = string.Empty;

        return Task.CompletedTask;
    }

    private Task SaveEditor()
    {
        if ( editorDraft is null )
            return Task.CompletedTask;

        editorDraft.Title = string.IsNullOrWhiteSpace( editorTitle )
            ? "Untitled task"
            : editorTitle.Trim();

        if ( string.IsNullOrEmpty( editorTargetId ) )
        {
            editorDraft.Id ??= $"task-{nextId++}";
            editorDraft.ParentId = editorParentId;
            tasks.Add( editorDraft.Clone() );
            lastAction = editorParentId is null
                ? $"Created {editorDraft.Title}"
                : $"Created child {editorDraft.Title}";
        }
        else
        {
            var existingTask = tasks.FirstOrDefault( x => x.Id == editorTargetId );

            if ( existingTask is not null )
            {
                existingTask.Title = editorDraft.Title;
                lastAction = $"Updated {existingTask.Title}";
            }
        }

        return CloseEditor();
    }

    private static void RemoveTaskWithChildren( List<TaskItem> list, string itemId )
    {
        var idsToDelete = new HashSet<string>( StringComparer.Ordinal ) { itemId };
        var changed = true;

        while ( changed )
        {
            changed = false;

            foreach ( var task in list )
            {
                if ( task.ParentId is not null && idsToDelete.Contains( task.ParentId ) && idsToDelete.Add( task.Id ) )
                    changed = true;
            }
        }

        list.RemoveAll( x => idsToDelete.Contains( x.Id ) );
    }

    private static List<TaskItem> CreateTasks()
    {
        var baseDate = DateTime.Today.AddDays( -2 );

        return new List<TaskItem>
        {
            new() { Id = "1", Title = "Website redesign", Start = baseDate, End = baseDate.AddDays( 14 ), Duration = 14 },
            new() { Id = "2", ParentId = "1", Title = "Discovery", Start = baseDate, End = baseDate.AddDays( 4 ), Duration = 4 },
            new() { Id = "3", ParentId = "1", Title = "Implementation", Start = baseDate.AddDays( 4 ), End = baseDate.AddDays( 12 ), Duration = 8 },
            new() { Id = "4", ParentId = "1", Title = "Launch", Start = baseDate.AddDays( 12 ), End = baseDate.AddDays( 14 ), Duration = 2 },
        };
    }

    public class TaskItem
    {
        public string Id { get; set; }

        public string ParentId { get; set; }

        public string Title { get; set; }

        public DateTime Start { get; set; }

        public DateTime End { get; set; }

        public int Duration { get; set; }

        public TaskItem Clone()
        {
            return new TaskItem
            {
                Id = Id,
                ParentId = ParentId,
                Title = Title,
                Start = Start,
                End = End,
                Duration = Duration,
            };
        }
    }
}

Multiple Views

Configure all timeline views in one Gantt instance, customize leading and trailing slots per view, and override week start day when needed.
Mar 16 - Mar 22, 2026
Task
Start
Project launch
Mar 18, 2026
Planning
Mar 18, 2026
Execution
Mar 22, 2026
Backend
Mar 23, 2026
Frontend
Mar 26, 2026
Go-live
Apr 03, 2026
Fri 13
Sat 14
Sun 15
Mon 16
Tue 17
Wed 18
Thu 19
Fri 20
Sat 21
Sun 22
Mon 23
Tue 24
Wed 25
Project launch
Planning
Execution
Backend

Current date: 3/20/2026 | View: Week

<Gantt TItem="TaskItem"
       Data="@tasks"
       @bind-Date="@selectedDate"
       @bind-SelectedView="@selectedView"
       FirstDayOfWeek="DayOfWeek.Sunday"
       DurationField="Duration">
    <GanttColumns>
        <GanttColumn Field="Title" Title="Task" Expandable Width="Width.Px(220)" />
        <GanttColumn Field="Start" Width="Width.Px(130)" />
        <GanttColumn Field="End" Width="Width.Px(130)" Visible="false" />
        <GanttColumn Field="Duration" Width="Width.Px(90)" TextAlignment="TextAlignment.Center" Visible="false" />
    </GanttColumns>
    <GanttToolbar />
    <GanttViews>
        <GanttDayView TimelineCellWidth="56" RowHeight="44" LeadingSlots="2" TrailingSlots="2" />
        <GanttWeekView TimelineCellWidth="92" RowHeight="44" LeadingSlots="3" TrailingSlots="3" FirstDayOfWeek="DayOfWeek.Monday" />
        <GanttMonthView TimelineCellWidth="38" RowHeight="44" LeadingSlots="5" TrailingSlots="5" />
        <GanttYearView TimelineCellWidth="80" RowHeight="44" LeadingSlots="1" TrailingSlots="1" />
    </GanttViews>
</Gantt>

<Paragraph TextColor="TextColor.Muted" Margin="Margin.Is2.FromTop">
    Current date: @selectedDate | View: @selectedView
</Paragraph>
@code {
    private DateOnly selectedDate = DateOnly.FromDateTime( DateTime.Today );

    private GanttView selectedView = GanttView.Week;

    private List<TaskItem> tasks = CreateTasks();

    private static List<TaskItem> CreateTasks()
    {
        var baseDate = DateTime.Today.AddDays( -2 );

        var result = new List<TaskItem>
        {
            new() { Id = "1", Title = "Project launch", Start = baseDate, End = baseDate.AddDays( 18 ) },
            new() { Id = "2", ParentId = "1", Title = "Planning", Start = baseDate, End = baseDate.AddDays( 4 ) },
            new() { Id = "3", ParentId = "1", Title = "Execution", Start = baseDate.AddDays( 4 ), End = baseDate.AddDays( 16 ) },
            new() { Id = "4", ParentId = "3", Title = "Backend", Start = baseDate.AddDays( 5 ), End = baseDate.AddDays( 11 ) },
            new() { Id = "5", ParentId = "3", Title = "Frontend", Start = baseDate.AddDays( 8 ), End = baseDate.AddDays( 15 ) },
            new() { Id = "6", ParentId = "1", Title = "Go-live", Start = baseDate.AddDays( 16 ), End = baseDate.AddDays( 18 ) },
        };

        foreach ( var item in result )
        {
            item.Duration = Math.Max( 1, (int)Math.Ceiling( ( item.End - item.Start ).TotalDays ) );
        }

        return result;
    }

    public class TaskItem
    {
        public string Id { get; set; }

        public string ParentId { get; set; }

        public string Title { get; set; }

        public DateTime Start { get; set; }

        public DateTime End { get; set; }

        public int Duration { get; set; }
    }
}

Auto Expand View

Enable AutoExpandView when the visible range should follow the loaded task dates instead of the bound Date. This sample keeps the anchor date intentionally outside the task range, so switching the toggle off shows the default date-based range again.
Feb 24 - Apr 07, 2026
Task
Start
Auto-expand release
Feb 25, 2026
Design phase
Feb 25, 2026
Implementation
Mar 04, 2026
Backend services
Mar 06, 2026
Frontend polish
Mar 13, 2026
Validation and rollout
Mar 27, 2026
February 2026
March 2026
April 2026
Tue 24
Wed 25
Thu 26
Fri 27
Sat 28
Sun 01
Mon 02
Tue 03
Wed 04
Thu 05
Fri 06
Sat 07
Sun 08
Mon 09
Tue 10
Wed 11
Thu 12
Fri 13
Sat 14
Sun 15
Mon 16
Tue 17
Wed 18
Thu 19
Fri 20
Sat 21
Sun 22
Mon 23
Tue 24
Wed 25
Thu 26
Fri 27
Sat 28
Sun 29
Mon 30
Tue 31
Wed 01
Thu 02
Fri 03
Sat 04
Sun 05
Mon 06
Tue 07
Auto-expand release
Design phase
Implementation
Backend services
Frontend polish
Validation and rollout

Anchor date: 12/20/2025 | View: Week | AutoExpandView: True

<Field Margin="Margin.Is3.FromBottom">
    <Switch @bind-Value="@autoExpandView">Auto expand current view to the loaded task range</Switch>
</Field>

<Gantt TItem="TaskItem"
       Data="@tasks"
       @bind-Date="@selectedDate"
       @bind-SelectedView="@selectedView"
       AutoExpandView="@autoExpandView"
       DurationField="Duration">
    <GanttColumns>
        <GanttColumn Field="Title" Title="Task" Expandable Width="Width.Px( 220 )" />
        <GanttColumn Field="Start" Width="Width.Px( 130 )" />
        <GanttColumn Field="End" Width="Width.Px( 130 )" Visible="false" />
        <GanttColumn Field="Duration" Width="Width.Px( 90 )" TextAlignment="TextAlignment.Center" Visible="false" />
    </GanttColumns>
    <GanttToolbar />
    <GanttViews>
        <GanttWeekView TimelineCellWidth="92" RowHeight="44" />
        <GanttMonthView TimelineCellWidth="38" RowHeight="44" />
        <GanttYearView TimelineCellWidth="84" RowHeight="44" />
    </GanttViews>
</Gantt>

<Paragraph TextColor="TextColor.Muted" Margin="Margin.Is2.FromTop">
    Anchor date: @selectedDate | View: @selectedView | AutoExpandView: @autoExpandView
</Paragraph>
@code {
    private bool autoExpandView = true;

    private DateOnly selectedDate = DateOnly.FromDateTime( DateTime.Today.AddMonths( -3 ) );

    private GanttView selectedView = GanttView.Week;

    private List<TaskItem> tasks = CreateTasks();

    private static List<TaskItem> CreateTasks()
    {
        DateTime rangeStart = new DateTime( DateTime.Today.Year, DateTime.Today.Month, 1 ).AddDays( -4 );

        List<TaskItem> result = new()
        {
            new() { Id = "1", Title = "Auto-expand release", Start = rangeStart, End = rangeStart.AddDays( 41 ) },
            new() { Id = "2", ParentId = "1", Title = "Design phase", Start = rangeStart, End = rangeStart.AddDays( 8 ) },
            new() { Id = "3", ParentId = "1", Title = "Implementation", Start = rangeStart.AddDays( 7 ), End = rangeStart.AddDays( 28 ) },
            new() { Id = "4", ParentId = "3", Title = "Backend services", Start = rangeStart.AddDays( 9 ), End = rangeStart.AddDays( 18 ) },
            new() { Id = "5", ParentId = "3", Title = "Frontend polish", Start = rangeStart.AddDays( 16 ), End = rangeStart.AddDays( 31 ) },
            new() { Id = "6", ParentId = "1", Title = "Validation and rollout", Start = rangeStart.AddDays( 30 ), End = rangeStart.AddDays( 41 ) },
        };

        foreach ( TaskItem item in result )
        {
            item.Duration = Math.Max( 1, (int)Math.Ceiling( ( item.End - item.Start ).TotalDays ) );
        }

        return result;
    }

    public class TaskItem
    {
        public string Id { get; set; }

        public string ParentId { get; set; }

        public string Title { get; set; }

        public DateTime Start { get; set; }

        public DateTime End { get; set; }

        public int Duration { get; set; }
    }
}

Template Customization

Customize multiple Gantt surfaces with templates, including header cells, tree cells, command cells, timeline headers, and task bars.
Mar 16 - Mar 22, 2026
Task
Duration
Platform update
13d
Core services
7d
Web client
7d
Release prep
2d
Mon 16
Tue 17
Wed 18
Thu 19
Fri 20
Sat 21
Sun 22
Platform update
Core services
Web client
<Gantt TItem="TaskItem"
       Data="@tasks"
       Date="@selectedDate"
       SelectedView="GanttView.Week"
       DurationField="Duration"
       Editable>
    <ChildContent>
        <GanttColumns>
            <GanttColumn Field="Title" Title="Task" Expandable Width="Width.Px(230)">
                <HeaderTemplate>
                    <Icon Name="IconName.List" Margin="Margin.Is1.FromEnd" />
                    <Span>@context.Text</Span>
                </HeaderTemplate>
            </GanttColumn>
            <GanttColumn Field="Duration" Width="Width.Px(90)" TextAlignment="TextAlignment.Center">
                <DisplayTemplate>
                    <Badge Color="Color.Info" Pill>@($"{context.Value}d")</Badge>
                </DisplayTemplate>
            </GanttColumn>
            <GanttCommandColumn Width="Width.Px(176)">
                <DisplayTemplate>
                    @if ( context.CanAddChild )
                    {
                        <Button Size="Size.ExtraSmall" Color="Color.Secondary" Outline Margin="Margin.Is1.FromEnd" Clicked="@context.AddChild">Child</Button>
                    }
                    @if ( context.CanEdit )
                    {
                        <Button Size="Size.ExtraSmall" Color="Color.Primary" Outline Margin="Margin.Is1.FromEnd" Clicked="@context.Edit">Edit</Button>
                    }
                    @if ( context.CanDelete )
                    {
                        <Button Size="Size.ExtraSmall" Color="Color.Danger" Outline Clicked="@context.Delete">Delete</Button>
                    }
                </DisplayTemplate>
            </GanttCommandColumn>
        </GanttColumns>

        <GanttToolbar />

        <GanttViews>
            <GanttWeekView TimelineCellWidth="92" RowHeight="44" />
        </GanttViews>
    </ChildContent>

    <TimelineHeaderCellTemplate>
        <Span TextSize="TextSize.Small" TextWeight="TextWeight.SemiBold">
            @context.Start.ToString( "ddd dd" )
        </Span>
    </TimelineHeaderCellTemplate>

    <TaskItemTemplate>
        <Span TextWeight="TextWeight.SemiBold">@context.Item.Title</Span>
    </TaskItemTemplate>
</Gantt>
@code {
    private DateOnly selectedDate = DateOnly.FromDateTime( DateTime.Today );

    private List<TaskItem> tasks = CreateTasks();

    private static List<TaskItem> CreateTasks()
    {
        var baseDate = DateTime.Today.AddDays( -2 );

        var result = new List<TaskItem>
        {
            new() { Id = "1", Title = "Platform update", Start = baseDate, End = baseDate.AddDays( 13 ) },
            new() { Id = "2", ParentId = "1", Title = "Core services", Start = baseDate, End = baseDate.AddDays( 7 ) },
            new() { Id = "3", ParentId = "1", Title = "Web client", Start = baseDate.AddDays( 4 ), End = baseDate.AddDays( 11 ) },
            new() { Id = "4", ParentId = "1", Title = "Release prep", Start = baseDate.AddDays( 11 ), End = baseDate.AddDays( 13 ) },
        };

        foreach ( var item in result )
        {
            item.Duration = Math.Max( 1, (int)Math.Ceiling( ( item.End - item.Start ).TotalDays ) );
        }

        return result;
    }

    public class TaskItem
    {
        public string Id { get; set; }

        public string ParentId { get; set; }

        public string Title { get; set; }

        public DateTime Start { get; set; }

        public DateTime End { get; set; }

        public int Duration { get; set; }
    }
}

API

Parameters

Gantt

Parameter Description TypeDefault
ActionColumnWidth

Gets or sets action column width in pixels.

double42d
AddChildCommandAllowed

Gets or sets whether creating child items is allowed.

booltrue
AutoExpandView

Gets or sets whether the active view range automatically expands to include all items.

boolfalse
ChildContent

Gets or sets child content used to declare toolbar and views.

RenderFragmentnull
Data

Gets or sets data source displayed by the Gantt.

IEnumerable<TItem>null
Date

Gets or sets current anchor date used by selected view.

DateOnlyDateOnly.FromDateTime( DateTime.Today )
DateColumnWidth

Gets or sets fallback date column width in pixels used when an auto-sized value cannot be calculated.

double140d
DeleteCommandAllowed

Gets or sets whether deleting existing items is allowed.

booltrue
DescriptionField

Gets or sets description field name.

string"Description"
Draggable

Gets or sets whether timeline item bars can be dragged to move their start and end dates together.

booltrue
DurationField

Gets or sets duration (days) field name.

string"Duration"
Editable

Gets or sets whether item editing is enabled.

boolfalse
EditCommandAllowed

Gets or sets whether editing existing items is allowed.

booltrue
EndField

Gets or sets end date field name.

string"End"
FirstDayOfWeek

Gets or sets first day of week used by weekly calculations.

DayOfWeekDayOfWeek.Monday
HeaderRowHeight

Gets or sets header row height in pixels.

doubleDefaultHeaderRowHeight
HierarchicalData

Gets or sets whether hierarchical data mode is forced when both parent-id and items mapping exist.

boolfalse
IdField

Gets or sets item identifier field name.

string"Id"
ItemsField

Gets or sets child item collection field name.

string"Items"
KeyboardNavigation

Gets or sets whether basic keyboard navigation is enabled for tree rows.

booltrue
Localizers

Gets or sets custom localizers for Gantt texts.

GanttLocalizersnull
MinBarWidth

Gets or sets minimum item bar width in pixels.

double14d
NewCommandAllowed

Gets or sets whether creating new top-level items is allowed.

booltrue
ParentIdField

Gets or sets parent identifier field name.

string"ParentId"
ProgressField

Gets or sets progress field name.

string"Progress"
Resizable

Gets or sets whether timeline item bars can be resized by dragging their start and end edges.

booltrue
SearchInputWidth

Gets or sets search input width in pixels.

doubleDefaultSearchInputWidth
SearchText

Gets or sets search text used to filter tree rows.

string
SelectedRow

Gets or sets currently selected tree row item.

TItemnull
SelectedView

Gets or sets currently selected view mode.

Possible values:Day, Week, Month, Year

GanttViewGanttView.Week
ShowToggleAllCommands

Gets or sets whether toggle-all commands (expand/collapse all) are visible in the toolbar.

booltrue
ShowToolbar

Gets or sets whether toolbar is rendered.

booltrue
Sortable

Gets or sets whether tree column sorting is enabled.

booltrue
StartField

Gets or sets start date field name.

string"Start"
TaskItemTemplate

Gets or sets template used to render timeline task content.

RenderFragment<GanttItemContext<TItem>>null
TimelineHeaderCellTemplate

Gets or sets template used to render timeline header cells.

RenderFragment<GanttTimelineHeaderCellContext>null
TitleColumnWidth

Gets or sets title column width in pixels.

double320d
TitleField

Gets or sets title field name.

string"Title"
TreeCommandCellTemplate

Gets or sets template used to render command cell content.

RenderFragment<GanttTreeCommandCellContext<TItem>>null
TreeCommandHeaderTemplate

Gets or sets template used to render command header content.

RenderFragment<GanttTreeCommandHeaderContext<TItem>>null
TreeIndentSize

Gets or sets tree indentation size per level in pixels.

double18d
TreeToggleWidth

Gets or sets tree toggle placeholder width in pixels.

doubleDefaultTreeToggleWidth
UseInternalEditing

Gets or sets whether built-in modal editing and internal data mutation are used.

booltrue

GanttColumn

Parameter Description TypeDefault
CellsEditableOnEditCommand

Gets or sets whether this column is editable during edit-item command.

booltrue
CellsEditableOnNewCommand

Gets or sets whether this column is editable during new-item command.

booltrue
Displayable

Gets or sets whether column can be shown in column picker.

booltrue
DisplayFormat

Gets or sets display format for default display text.

string
DisplayFormatProvider

Gets or sets display format provider.

IFormatProvidernull
DisplayTemplate

Gets or sets custom display template.

RenderFragment<GanttColumnDisplayContext<TItem>>null
Editable

Gets or sets whether this column is editable in edit forms.

booltrue
EditTemplate

Gets or sets custom edit template.

RenderFragment<GanttColumnEditContext<TItem>>null
Expandable

Gets or sets whether this column should render tree expander.

boolfalse
Field

Field name bound to this column.

string
HeaderTemplate

Gets or sets custom header template.

RenderFragment<GanttColumnHeaderContext<TItem>>null
Sortable

Gets or sets whether this column can be sorted.

booltrue
SortField

Gets or sets field used by sort operation. Defaults to Field.

string
TextAlignment

Gets or sets text alignment for header and cell.

Possible values:Default, Start, End, Center, Justified

TextAlignmentDefault
Title

Optional title shown in header.

string
Visible

Gets or sets whether column is currently visible.

booltrue
Width

Gets or sets width.

IFluentSizingnull

GanttCommandColumn

Parameter Description TypeDefault
Displayable

Gets or sets whether column can be shown in column picker.

booltrue
DisplayFormat

Gets or sets display format for default display text.

string
DisplayFormatProvider

Gets or sets display format provider.

IFormatProvidernull
DisplayTemplate

Gets or sets custom command display template.

RenderFragment<GanttCommandColumnDisplayContext<TItem>>null
EditTemplate

Gets or sets custom edit template.

RenderFragment<GanttColumnEditContext<TItem>>null
Expandable

Gets or sets whether this column should render tree expander.

boolfalse
Field

Field name bound to this column.

string
HeaderTemplate

Gets or sets custom header template.

RenderFragment<GanttColumnHeaderContext<TItem>>null
Sortable

Gets or sets whether this column can be sorted.

booltrue
SortField

Gets or sets field used by sort operation. Defaults to Field.

string
TextAlignment

Gets or sets text alignment for header and cell.

Possible values:Default, Start, End, Center, Justified

TextAlignmentDefault
Title

Optional title shown in header.

string
Visible

Gets or sets whether column is currently visible.

booltrue
Width

Gets or sets width.

IFluentSizingnull

GanttDayView

Parameter Description TypeDefault
ItemTemplate

Template for rendering the timeline item bar.

RenderFragment<GanttItemContext<TItem>>null
LeadingSlots

Number of extra slots shown before the anchor period.

int0
RowHeight

Height of each timeline row in pixels.

double44
RowTemplate

Template for rendering the row cell.

RenderFragment<GanttRowContext<TItem>>null
TimelineCellWidth

Width of each timeline cell in pixels.

double72
TrailingSlots

Number of extra slots shown after the anchor period.

int0

GanttWeekView

Parameter Description TypeDefault
FirstDayOfWeek

Optional first day of week override for week view calculations.

DayOfWeek?null
ItemTemplate

Template for rendering the timeline item bar.

RenderFragment<GanttItemContext<TItem>>null
LeadingSlots

Number of extra slots shown before the anchor period.

int0
RowHeight

Height of each timeline row in pixels.

double44
RowTemplate

Template for rendering the row cell.

RenderFragment<GanttRowContext<TItem>>null
TimelineCellWidth

Width of each timeline cell in pixels.

double72
TrailingSlots

Number of extra slots shown after the anchor period.

int0

GanttMonthView

Parameter Description TypeDefault
ItemTemplate

Template for rendering the timeline item bar.

RenderFragment<GanttItemContext<TItem>>null
LeadingSlots

Number of extra slots shown before the anchor period.

int0
RowHeight

Height of each timeline row in pixels.

double44
RowTemplate

Template for rendering the row cell.

RenderFragment<GanttRowContext<TItem>>null
TimelineCellWidth

Width of each timeline cell in pixels.

double72
TrailingSlots

Number of extra slots shown after the anchor period.

int0

GanttYearView

Parameter Description TypeDefault
ItemTemplate

Template for rendering the timeline item bar.

RenderFragment<GanttItemContext<TItem>>null
LeadingSlots

Number of extra slots shown before the anchor period.

int0
RowHeight

Height of each timeline row in pixels.

double44
RowTemplate

Template for rendering the row cell.

RenderFragment<GanttRowContext<TItem>>null
TimelineCellWidth

Width of each timeline cell in pixels.

double72
TrailingSlots

Number of extra slots shown after the anchor period.

int0

Events

Gantt

Event Description Type
AddChildItemClicked

Gets or sets callback invoked when the add-child command is triggered.

EventCallback<GanttCommandContext<TItem>>
CommandAllowed

Gets or sets callback used to allow or deny command execution per item.

Func<GanttCommandContext<TItem>, bool>
DateChanged

Gets or sets callback raised when Date changes.

EventCallback<DateOnly>
DeleteItemClicked

Gets or sets callback invoked when delete action is triggered for item.

EventCallback<GanttItemClickedEventArgs<TItem>>
EditItemClicked

Gets or sets callback invoked when edit action is triggered for item.

EventCallback<GanttItemClickedEventArgs<TItem>>
ItemClicked

Gets or sets callback invoked when a timeline item is clicked.

EventCallback<GanttItemClickedEventArgs<TItem>>
ItemInserted

Gets or sets callback invoked after item insertion.

EventCallback<GanttInsertedItem<TItem>>
ItemInserting

Gets or sets callback invoked before an item is inserted.

EventCallback<GanttCancellableItemChange<TItem>>
ItemRemoved

Gets or sets callback invoked after item removal.

EventCallback<GanttUpdatedItem<TItem>>
ItemRemoving

Gets or sets callback invoked before an item is removed.

EventCallback<GanttCancellableItemChange<TItem>>
ItemStyling

Gets or sets item styling callback for timeline bars.

Action<TItem, GanttItemStyling>
ItemUpdated

Gets or sets callback invoked after item update.

EventCallback<GanttUpdatedItem<TItem>>
ItemUpdating

Gets or sets callback invoked before an item is updated.

EventCallback<GanttCancellableItemChange<TItem>>
NewIdCreator

Gets or sets custom factory used to create new item identifiers.

Func<object>
NewItemClicked

Gets or sets callback invoked when the new-item command is triggered.

EventCallback<GanttCommandContext<TItem>>
NewItemCreator

Gets or sets custom factory used to create new item instances.

Func<TItem>
ReadData

Gets or sets callback used for API-style data reads.

EventCallback<GanttReadDataEventArgs<TItem>>
SearchTextChanged

Gets or sets callback raised when SearchText changes.

EventCallback<string>
SelectedRowChanged

Gets or sets callback raised when SelectedRow changes.

EventCallback<TItem>
SelectedViewChanged

Gets or sets callback raised when SelectedView changes.

EventCallback<GanttView>

Methods

Gantt

Method DescriptionReturnParameters
AddChild Creates a new child item for specified parent. TaskTItem parentItem
CollapseAll Collapses all nodes in the tree, including all nested child nodes. Task
Delete Deletes specified item. TaskTItem item
Edit Puts chart in edit-item state for specified item. TaskTItem item
ExpandAll Expands all nodes in the tree, including all nested child nodes. Task
GetState Gets current Gantt state. Task<GanttState<TItem>>
LoadState Loads and applies Gantt state. TaskGanttState<TItem> ganttState
NavigateNextPeriod Navigates to the next period based on the selected view. Task
NavigatePreviousPeriod Navigates to the previous period based on the selected view. Task
NavigateToday Navigates the chart to current date. Task
New Creates a new item using configured new-item factory. Task
New Creates a new top-level item. TaskTItem item
New Puts chart in new-item editing state. TaskTItem item, TItem parentItem
NotifyBarDragMouseMove Receives JavaScript drag-move notifications for the active timeline item drag operation. Taskdouble clientX
NotifyBarDragMouseUp Receives JavaScript drag-end notifications for the active timeline item drag operation. Taskdouble clientX, bool dragged
ShowDayView Switches to Day view. Task
ShowMonthView Switches to Month view. Task
ShowWeekView Switches to Week view. Task
ShowYearView Switches to Year view. Task

GanttColumn

Method DescriptionReturnParameters
CellValueIsEditable Gets whether the column value is editable for current edit state. boolGanttEditState editState
CanSort Returns true when column can be sorted. bool
FormatDisplayValue Gets formatted display text for this column. stringobject value
GetSortField Gets field name to sort by. string
GetSortValue Gets raw value used for sorting. objectTItem item
GetValue Gets raw value for this column. objectTItem item

GanttCommandColumn

Method DescriptionReturnParameters
CanSort Returns true when column can be sorted. bool
FormatDisplayValue Gets formatted display text for this column. stringobject value
GetSortField Gets field name to sort by. string
GetSortValue Gets raw value used for sorting. objectTItem item
GetValue Gets raw value for this column. objectTItem item
On this page