Skip to content

documentation(950115):Virtualization with hierarchical data binding #6131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 34 commits into
base: development
Choose a base branch
from
Open
Changes from 4 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
795c6a3
documentation(950115):Virtualization with hierarchical data binding
JamunaSundaramSF3699 Jun 13, 2025
5112b5f
documentation(950115):Virtualization with hierarchical data binding
JamunaSundaramSF3699 Jun 13, 2025
62ddb33
documentation(950115):Virtualization with hierarchical data binding
JamunaSundaramSF3699 Jun 13, 2025
1a80167
documentation(950115):Virtualization with hierarchical data binding
JamunaSundaramSF3699 Jun 13, 2025
49c3497
documentation(950115):updated
JamunaSundaramSF3699 Jun 17, 2025
9f3f352
documentation(950115):updated
JamunaSundaramSF3699 Jun 17, 2025
15ffa52
Merge branch 'development' into 950115-sam
jmfarook7 Jun 17, 2025
02b67ff
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 18, 2025
5f85be7
Merge branch '950115-sam' of https://github.com/syncfusion-content/bl…
JamunaSundaramSF3699 Jun 18, 2025
1094069
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 18, 2025
b81199b
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 18, 2025
79e6d01
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 18, 2025
1c76d2d
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 18, 2025
d4ee16d
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 18, 2025
aa57fd3
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 18, 2025
5bc81e6
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 18, 2025
40b2170
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 18, 2025
0a40457
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 19, 2025
48bbbbf
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 19, 2025
096d990
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 19, 2025
91b1765
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 19, 2025
db726bb
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 19, 2025
4780b21
documentation(950115):Updated the content.
JamunaSundaramSF3699 Jun 19, 2025
87cbdfc
documentation(950115): updated
farveensulthana Jun 19, 2025
e8b8a63
documentation(950115):Updated.
JamunaSundaramSF3699 Jun 23, 2025
9547bed
documentation(950115):Updated.
JamunaSundaramSF3699 Jun 23, 2025
69cb084
documentation(950115):Updated.
JamunaSundaramSF3699 Jun 23, 2025
75541bb
documentation(950115):Updated.
JamunaSundaramSF3699 Jun 23, 2025
ea9d986
documentation(950115):Updated.
JamunaSundaramSF3699 Jun 23, 2025
145252b
documentation(950115):Updated.
JamunaSundaramSF3699 Jun 23, 2025
2a979af
documentation(950115):Updated.
JamunaSundaramSF3699 Jun 23, 2025
147875c
Merge branch 'development' into 950115-sam
JamunaSundaramSF3699 Jun 24, 2025
6377900
Merge branch 'development' into 950115-sam
JamunaSundaramSF3699 Jun 24, 2025
129ff44
Merge branch 'development' into 950115-sam
JamunaSundaramSF3699 Jun 24, 2025
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
293 changes: 293 additions & 0 deletions blazor/treegrid/virtualization.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,299 @@ By default, the number of records rendered per page will be twice the TreeGrid's

N> For example, when the OverscanCount is set to 5, only 5 buffer rows are rendered on the first and last pages. However, on in-between pages, a total of 10 buffer rows are rendered, with 5 rows allocated for both before and after the current page's visible rows.


## Virtualization with hierarchical data binding

In [hierarchical data binding]((https://blazor.syncfusion.com/documentation/treegrid/data-binding#hierarchy-data-binding)), each parent record in the data source contains a nested collection of child records, representing a tree-like structure. When working with large hierarchical datasets, enabling virtualization helps significantly improve performance and rendering efficiency.

Virtualization with hierarchical data binding in the TreeGrid is a performance optimization technique that allows only the visible rows within the viewport (and a few buffer rows) to be rendered at any given time, rather than the entire dataset. This approach ensures smooth scrolling and minimal memory usage, especially when displaying complex parent-child relationships across thousands of rows.

* When using virtualization with hierarchical data binding, the data source should follow a flattened hierarchical structure, where each parent record is immediately followed by its child records in the correct sequence.

* This differs from earlier implementations where only the top-level parent records were initially bound, and child data was loaded or rendered separately.

* To ensure proper rendering and efficient virtual scrolling, the TreeGrid uses an internal helper method to flatten the hierarchical dataset. This method restructures the data while preserving the logical parent-child relationships and display order,, which is essential for supporting operations like expand and collapse behavior, virtual scrolling across all hierarchy levels.

* This structure makes rendering efficient and ensures smooth interactions when working with large hierarchical datasets in a virtualized environment.

To enable virtualization with hierarchical data binding, follow these steps to convert the hierarchical data into a self-referential, flattened structure handled on the application side before binding the data to the component:

**Step 1: Enabling virtualization with hierarchical binding properties:**

Set the [enableVirtualization](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.SfGrid-1.html#Syncfusion_Blazor_Grids_SfGrid_1_EnableVirtualization) property to **true** to enable virtualization. Additionally, when using hierarchical data binding, enable the [childMapping](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.TreeGrid.SfTreeGrid-1.html#Syncfusion_Blazor_TreeGrid_SfTreeGrid_1_ChildMapping) property to specify the child records collection.

**Step 2: Initialize the flattened data in the component lifecycle:**

Use the `HierarchyToFlatData` method to convert the hierarchical data into a flattened array and bind it to the TreeGrid's data source.

```ts

protected override void OnInitialized()
{
this.TreeGridData = HierarchyToFlatData(VirtualData.GetVirtualData(), "Children").ToArray();
}

```

**Step 3: Flatten the hierarchical data source:**

To flatten the data, implement a recursive method that processes each parent and appends its children immediately after it, maintaining the display order.

```ts

public List<VirtualData> HierarchyToFlatData(List<VirtualData> dataSource, string childMapping, List<VirtualData> addedData = null)
{
if (addedData == null)
{
addedData = new List<VirtualData>();
}

foreach (var item in dataSource)
{
addedData.Add(item);

// Get children dynamically using reflection.
var propertyInfo = item.GetType().GetProperty(childMapping);
var children = propertyInfo?.GetValue(item) as IEnumerable<VirtualData>;

if (children != null)
{
HierarchyToFlatData(children.ToList(), childMapping, addedData);
}
}
return addedData;
}

```


**Step 4: Define the data model:**

Create a data model class that contains hierarchical data with a collection of child records.

```ts

public class VirtualData
{
public int TaskID { get; set; }
public string FIELD1 { get; set; }
public int FIELD2 { get; set; }
public int? FIELD3 { get; set; }
public int? FIELD4 { get; set; }
ublic List<VirtualData> Children { get; set; }

static string[] Names = new string[] { "VINET", "TOMSP", "HANAR", "VICTE", "SUPRD", "HANAR", "CHOPS", "RICSU", "WELLI", "HILAA", "ERNSH", "CENTC","OTTIK", "QUEDE", "RATTC", "ERNSH", "FOLKO", "BLONP", "WARTH", "FRANK", "GROSR", "WHITC", "WARTH", "SPLIR", "RATTC", "QUICK", "VINET","MAGAA", "TORTU", "MORGK", "BERGS", "LEHMS", "BERGS", "ROMEY", "ROMEY", "LILAS", "LEHMS", "QUICK", "QUICK", "RICAR", "REGGC", "BSBEV","COMMI", "QUEDE", "TRADH", "TORTU", "RATTC", "VINET", "LILAS", "BLONP", "HUNGO", "RICAR", "MAGAA", "WANDK", "SUPRD", "GODOS", "TORTU","OLDWO", "ROMEY", "LONEP", "ANATR", "HUNGO", "THEBI", "DUMON", "WANDK", "QUICK", "RATTC", "ISLAT", "RATTC", "LONEP", "ISLAT", "TORTU","WARTH", "ISLAT", "PERIC", "KOENE", "SAVEA", "KOENE", "BOLID", "FOLKO", "FURIB", "SPLIR", "LILAS", "BONAP", "MEREP", "WARTH", "VICTE","HUNGO", "PRINI", "FRANK", "OLDWO", "MEREP", "BONAP", "SIMOB", "FRANK", "LEHMS", "WHITC", "QUICK", "RATTC", "FAMIA" };

public static List<VirtualData> GetVirtualData()
{
List<VirtualData> DataCollection = new List<VirtualData>();
var j = 0;
for (var i = 1; i <= 10000; i++)
{

var random = new Random();
var name = random.Next(50);
VirtualData Parent1 = new VirtualData()
{
TaskID = ++j,
FIELD1 = VirtualData.Names[name],
FIELD2 = 1967,
FIELD3 = 395,
FIELD4 = 87,
Children = new List<VirtualData>()
};
for (var k = 0; k < 4; k++)
{
name = random.Next(5);
VirtualData Child1 = new VirtualData()
{
TaskID = ++j,
FIELD1 = VirtualData.Names[name],
FIELD2 = 1968,
FIELD3 = 295,
FIELD4 = 44
};
Parent1.Children.Add(Child1);
}

name = random.Next(50);
VirtualData Parent2 = new VirtualData()
{
TaskID = ++j,
FIELD1 = VirtualData.Names[name],
FIELD2 = 1968,
FIELD3 = 295,
FIELD4 = 44,
Children = new List<VirtualData>()
};
for (var m = 0; m < 4; m++)
{
name = random.Next(50);
VirtualData Child2 = new VirtualData()
{
TaskID = ++j,
FIELD1 = VirtualData.Names[name],
FIELD2 = 1968,
FIELD3 = 295,
FIELD4 = 44
};
Parent2.Children.Add(Child2);
}
DataCollection.Add(Parent1);
DataCollection.Add(Parent2);
}
return DataCollection;
}
}

```

The following sample demonstrates virtualization implementation with hierarchical data binding:

{% tabs %}
{% highlight razor tabtitle="Index.razor" %}

@using Syncfusion.Blazor.TreeGrid;
@using Syncfusion.Blazor.Grids;

<SfTreeGrid RowHeight="35" OverscanCount="5" @ref="TreeGrid" TValue="VirtualData" DataSource="@TreeGridData" ChildMapping="Children" EnableVirtualization="true" Height="400" TreeColumnIndex="1" EnableVirtualMaskRow="true" Toolbar="@(new List<string>(){"Add","Edit","Delete","Update","Cancel","ExpandAll", "CollapseAll"})">
<TreeGridEditSettings AllowEditing="true" AllowAdding="true" AllowDeleting="true" Mode="Syncfusion.Blazor.TreeGrid.EditMode.Cell" NewRowPosition="RowPosition.Child" />
<TreeGridPageSettings PageSize="30"></TreeGridPageSettings>
<TreeGridColumns>
<TreeGridColumn Field="TaskID" IsPrimaryKey="true" HeaderText="Player Jersey" Width="100" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right"></TreeGridColumn>
<TreeGridColumn Field="FIELD1" HeaderText="Player Name" Width="100"></TreeGridColumn>
<TreeGridColumn Field="FIELD2" HeaderText="Year" Width="100" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right"></TreeGridColumn>
<TreeGridColumn Field="FIELD3" HeaderText="Stint" Width="100" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right"></TreeGridColumn>
<TreeGridColumn Field="FIELD4" HeaderText="TMID" Width="80"></TreeGridColumn>
</TreeGridColumns>
</SfTreeGrid>

@code {
private SfTreeGrid<VirtualData> TreeGrid;
public VirtualData[] TreeGridData { get; set; }

protected override void OnInitialized()
{
this.TreeGridData = HierarchyToFlatData(VirtualData.GetVirtualData(), "Children").ToArray();
}

public List<VirtualData> HierarchyToFlatData(List<VirtualData> dataSource, string childMapping, List<VirtualData> addedData = null)
{
if (addedData == null)
{
addedData = new List<VirtualData>();
}

foreach (var item in dataSource)
{
addedData.Add(item);

// Get children dynamically using reflection.
var propertyInfo = item.GetType().GetProperty(childMapping);
var children = propertyInfo?.GetValue(item) as IEnumerable<VirtualData>;
if (children != null)
{
HierarchyToFlatData(children.ToList(), childMapping, addedData);
}
}

return addedData;
}

private async Task ExpandAllOnClick()
{
await TreeGrid.ExpandAllAsync();
}

public class VirtualData
{
public int TaskID { get; set; }
public string FIELD1 { get; set; }
public int FIELD2 { get; set; }
public int? FIELD3 { get; set; }
public int? FIELD4 { get; set; }
public List<VirtualData> Children { get; set; }

static string[] Names = new string[] { "VINET", "TOMSP", "HANAR", "VICTE", "SUPRD", "HANAR", "CHOPS", "RICSU", "WELLI", "HILAA", "ERNSH", "CENTC","OTTIK", "QUEDE", "RATTC", "ERNSH", "FOLKO", "BLONP", "WARTH", "FRANK", "GROSR", "WHITC", "WARTH", "SPLIR", "RATTC", "QUICK", "VINET","MAGAA", "TORTU", "MORGK", "BERGS", "LEHMS", "BERGS", "ROMEY", "ROMEY", "LILAS", "LEHMS", "QUICK", "QUICK", "RICAR", "REGGC", "BSBEV","COMMI", "QUEDE", "TRADH", "TORTU", "RATTC", "VINET", "LILAS", "BLONP", "HUNGO", "RICAR", "MAGAA", "WANDK", "SUPRD", "GODOS", "TORTU","OLDWO", "ROMEY", "LONEP", "ANATR", "HUNGO", "THEBI", "DUMON", "WANDK", "QUICK", "RATTC", "ISLAT", "RATTC", "LONEP", "ISLAT", "TORTU","WARTH", "ISLAT", "PERIC", "KOENE", "SAVEA", "KOENE", "BOLID", "FOLKO", "FURIB", "SPLIR", "LILAS", "BONAP", "MEREP", "WARTH", "VICTE","HUNGO", "PRINI", "FRANK", "OLDWO", "MEREP", "BONAP", "SIMOB", "FRANK", "LEHMS", "WHITC", "QUICK", "RATTC", "FAMIA" };

public static List<VirtualData> GetVirtualData()
{
List<VirtualData> DataCollection = new List<VirtualData>();
var j = 0;
for (var i = 1; i <= 10000; i++)
{
var random = new Random();
var name = random.Next(50);
VirtualData Parent1 = new VirtualData()
{
TaskID = ++j,
FIELD1 = VirtualData.Names[name],
FIELD2 = 1967,
FIELD3 = 395,
FIELD4 = 87,
Children = new List<VirtualData>()
};
for (var k = 0; k < 4; k++)
{
name = random.Next(5);
VirtualData Child1 = new VirtualData()
{
TaskID = ++j,
FIELD1 = VirtualData.Names[name],
FIELD2 = 1968,
FIELD3 = 295,
FIELD4 = 44
};
Parent1.Children.Add(Child1);
}

name = random.Next(50);
VirtualData Parent2 = new VirtualData()
{
TaskID = ++j,
FIELD1 = VirtualData.Names[name],
FIELD2 = 1968,
FIELD3 = 295,
FIELD4 = 44,
Children = new List<VirtualData>()
};
for (var m = 0; m < 4; m++)
{
name = random.Next(50);
VirtualData Child2 = new VirtualData()
{
TaskID = ++j,
FIELD1 = VirtualData.Names[name],
FIELD2 = 1968,
FIELD3 = 295,
FIELD4 = 44
};
Parent2.Children.Add(Child2);
}
DataCollection.Add(Parent1);
DataCollection.Add(Parent2);
}
return DataCollection;
}
}
}

{% endhighlight %}
{% endtabs %}


By organizing the data in this format, the TreeGrid can efficiently render large hierarchical datasets with virtualization enabled.

**Limitations:**

* ExpandCollapse State maintenance is not supported for Hierarchy Data.

* Batch Editing is not supported for Hierarchy Data.

* Row Drag and Drop feature is not supported for Hierarchy Data.

* Additionally, please refer to the [virtualization limitations](https://blazor.syncfusion.com/documentation/treegrid/virtualization#limitations-for-virtualization) for more details on current constraints when using virtualization with hierarchical data.

## Column Virtualization

Column virtualization allows you to virtualize columns. It will render columns which are in the viewport. You can scroll horizontally to view more columns.
Expand Down