Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5dd1114
Add the HierarchicalGridItem basis and example
vnbaaij Jan 23, 2026
67ce127
- Add example with more than 1 level
vnbaaij Jan 26, 2026
f601886
- Add more tests and update veriefied files
vnbaaij Jan 26, 2026
8379b62
Update docs
vnbaaij Jan 26, 2026
82d522b
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/hierarchical-grid-item
vnbaaij Jan 26, 2026
bd4c811
- Add checks and tests so that only 1 HerarchicalToggle can exist and…
vnbaaij Jan 26, 2026
70c4698
Process review comments
vnbaaij Jan 26, 2026
ba2b182
Typo
vnbaaij Jan 26, 2026
8ccdad0
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/hierarchical-grid-item
vnbaaij Jan 26, 2026
fe7a9a1
Merge branch 'users/vnbaaij/dev-v5/hierarchical-grid-item' of https:/…
vnbaaij Jan 26, 2026
0aa23ae
Some optimizations for when using the DataGrid in rtl mode
vnbaaij Jan 27, 2026
5c0efc5
Store
vnbaaij Jan 28, 2026
c05ce32
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/hierarchical-grid-item
vnbaaij Jan 28, 2026
8af6147
Merge branch 'users/vnbaaij/dev-v5/hierarchical-grid-item' of https:/…
vnbaaij Jan 28, 2026
91b39cc
- Use addEventListener on gridElement instead of document
vnbaaij Jan 28, 2026
cbe7f60
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/hierarchical-grid-item
vnbaaij Jan 28, 2026
4426fc7
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/hierarchical-grid-item
dvoituron Jan 31, 2026
7594d25
merge
vnbaaij Feb 2, 2026
78e1fbe
Merge branch 'users/vnbaaij/dev-v5/hierarchical-grid-item' of https:/…
vnbaaij Feb 2, 2026
8fd2158
Fix script. Final tweaks
vnbaaij Feb 2, 2026
0b2a078
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/hierarchical-grid-item
vnbaaij Feb 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
@using static FluentUI.Demo.SampleData.Olympics2024

<FluentDataGrid Items="@items.Where(i => !i.IsHidden).AsQueryable()" ShowHover="true" ResizableColumns="true">
<TemplateColumn Title="Name" HierarchicalToggle="true">
@if (context.Item.ContinentCode != null)
{
<img class="flag" src="@(context.Item.Flag())" alt="Flag of @(context.Item.Code)" />
}
@context.Item.Name
</TemplateColumn>
<PropertyColumn Title="Gold" Property="@(i => i.Item.Medals.Gold)" />
<PropertyColumn Title="Silver" Property="@(i => i.Item.Medals.Silver)" Align="DataGridCellAlignment.Center" />
<PropertyColumn Title="Bronze" Property="@(i => i.Item.Medals.Bronze)" Align="DataGridCellAlignment.Center" />
<PropertyColumn Title="Total" Property="@(i => i.Item.Medals.Total)" Align="DataGridCellAlignment.End" />

</FluentDataGrid>

@code {
List<OlympicGridItem> items = new();

protected override void OnInitialized()
{
foreach (var continent in Continents)
{
var countries = Countries.Where(c => c.ContinentCode == continent.Code).OrderByDescending(c => c.Medals.Total);

var continentItem = new OlympicGridItem
{
Item = continent with
{
Medals = new Medals(
Gold: countries.Sum(c => c.Medals.Gold),
Silver: countries.Sum(c => c.Medals.Silver),
Bronze: countries.Sum(c => c.Medals.Bronze)
)
},
IsCollapsed = true
};

items.Add(continentItem);

foreach (var country in countries)
{
var countryItem = new OlympicGridItem
{
Item = country,
Depth = 1,
IsHidden = true
};
continentItem.Children.Add(countryItem);
items.Add(countryItem);
}
}
}

public class OlympicGridItem : HierarchicalGridItem<Country, OlympicGridItem>
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
:root {
--datagrid-hover-color: lightyellow;
}

.fluent-data-grid {
--fluent-data-grid-resize-handle-color: var(--colorNeutralStencil1) !important;
}

.flag {
height: 1rem;
border: 1px solid var(--colorNeutralBackground3);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@using FluentUI.Demo.SampleData
@using static FluentUI.Demo.SampleData.People

<FluentButton Appearance="ButtonAppearance.Primary" IconStart="@(ceoItem?.IsCollapsed == true ? new Icons.Regular.Size16.Add() : new Icons.Regular.Size16.Subtract())"
OnClick="@ToggleCEO">
@(ceoItem?.IsCollapsed == true ? "Expand" : "Collapse") CEO
</FluentButton>

<FluentDataGrid Items="@items.Where(i => !i.IsHidden).AsQueryable()" ResizableColumns="true">
<TemplateColumn Title="Name" HierarchicalToggle="true">
@(context.Item.FirstName + " " + context.Item.LastName)
</TemplateColumn>
<PropertyColumn Title="Job Title" Property="@(i => i.Item.JobTitle)" />
<PropertyColumn Title="Department" Property="@(i => i.Item.Department)" />
<PropertyColumn Title="Location" Property="@(i => i.Item.Location)" />
</FluentDataGrid>


Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// ------------------------------------------------------------------------
// This file is licensed to you under the MIT License.
// ------------------------------------------------------------------------

using Microsoft.FluentUI.AspNetCore.Components;
using static FluentUI.Demo.SampleData.People;

namespace FluentUI.Demo.Client.Documentation.Components.DataGrid.Examples;

public partial class DataGridHierarchicalOrgChart
{
private PersonGridItem? ceoItem;
private readonly List<PersonGridItem> items = [];

protected override void OnInitialized()
{
var allPeople = GeneratePersons(30).ToList();

// Level 0: CEO/Manager
var ceo = allPeople[0] with { FirstName = "Mads", LastName = "Torgersen", JobTitle = "CEO", Department = "Executive" };
ceoItem = new PersonGridItem
{
Item = ceo,
IsCollapsed = false
};
items.Add(ceoItem);

// ... existing code ...
for (var i = 1; i <= 3; i++)
{
var manager = allPeople[i] with { JobTitle = "Director", Department = "Engineering" };
var managerItem = new PersonGridItem { Item = manager, Depth = 1, IsCollapsed = i != 2 };
ceoItem.Children.Add(managerItem);
items.Add(managerItem);

// Level 2: Employees
for (var j = 0; j < 4; j++)
{
var employee = allPeople[4 + (i - 1) * 4 + j];
var employeeItem = new PersonGridItem { Item = employee, Depth = 2, IsHidden = i != 2 };
managerItem.Children.Add(employeeItem);
items.Add(employeeItem);
}
}
}

private void ToggleCEO()
{
if (ceoItem is not null)
{
ceoItem.IsCollapsed = !ceoItem.IsCollapsed;
}
}

public class PersonGridItem : HierarchicalGridItem<Person, PersonGridItem>
{
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* Ensure all the flags are the same size, and centered */
.flag {
height: 1rem;
border: 1px solid var(--neutral-layer-3);
height: 1rem;
border: 1px solid var(--colorNeutralBackground3);
}
.search-box {
min-width: 250px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ The following values can be localized:
- DataGrid_SortMenu
- DataGrid_SortMenuAscending
- DataGrid_SortMenuDescending
- DataGrid_ToggleNesting


## Using the DataGrid component with EF Core
Expand All @@ -95,8 +96,6 @@ builder.Services.AddDataGridEntityFrameworkAdapter();Copy

## Using the DataGrid component with OData

*Added in 4.11.0*

If you want to use the `FluentDataGrid` with data provided through OData, you need to install an additional package so the grid knows how to resolve queries asynchronously for efficiency.

### Installation
Expand Down Expand Up @@ -143,6 +142,7 @@ The following examples show how to use the DataGrid component in different scena
- [Custom comparer](/DataGrid/CustomComparerSort)
- [Virtualized grid](/DataGrid/Virtualize)
- [Remote data](/DataGrid/RemoteData)
- [Hierarchical grid](/DataGrid/HierarchicalDataGrid)
- [Manual grid](/DataGrid/ManualDataGrid)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ color by setting the `--datagrid-hover-color` CSS variable. See the Razor tab fo
To show how the resize handle can be altered, when choosing to use the alternate hover color, the handle color is set to a different value.

[!Note]: once a value has been selected for the Resize type, it cannot be set to null again. You need to refresh the page to start with a null value again.</em></p>


The resize options UI is using a customized string for the label ('Width (+/- 10px)' instead of the normal 'Column width').
This is done through the custom localizer which is registered in the Server project's Program.cs file.


{{ DataGridCustomComparer Files=Code:DataGridCustomComparer.razor;CSS:DataGridCustomComparer.razor.css }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
title: Hierarchical data
route: /DataGrid/Hierarchical
---

# Hierarchical data

## Single-level hierarchy

The `FluentDataGrid` supports displaying hierarchical data.

By using the `HierarchicalGridItem` class (or a class derived from it) as the grid item type,
you can define parent-child relationships between items.

Set the `HierarchicalToggle` parameter to `true` on one of the columns to display the expand/collapse button.

{{ DataGridHierarchical Files=Code:DataGridHierarchical.razor;CSS:DataGridHierarchical.razor.css}}

## Multi-level hierarchy

The hierarchical data grid can display multiple levels of nesting. In this example, we show an organization chart with three levels: CEO, Directors, and Employees.

This example also shows how to programmatically expand and collapse rows by manually setting the `IsCollapsed` property on a `HierarchicalGridItem` instance.

{{ DataGridHierarchicalOrgChart Files=Code:DataGridHierarchicalOrgChart.razor}}

Loading
Loading