I am trying to build multilevel Hierarchy TelerikGrid by hiding the default button and adding a custom Link. If a parent has sub list then the custom button will appear and on clicking the sub list button it should display details. I am not able to load the 3 level on button click. The second level is working good. I have sample partially working code.
@page "/custom-expand"
<TelerikGrid Data="@fileLists"
@ref="FileListGrid"
Class="no-default-hierarchy-column"
>
<DetailTemplate>
@{
var parent = context as FileList;
@if (parent.SubData?.Any() == true)
{
<TelerikGrid Data="parent.SubData" SelectionMode="Telerik.Blazor.GridSelectionMode.Multiple" Class="no-grid-header no-default-hierarchy-column" Height="100px">
<GridColumns>
<GridColumn Context="children" Width="15px">
<Template>
@{
var item = (FileName)children;
var isFirstChild = parent.SubData.IndexOf(item) == 0;
<TelerikCheckBox Value="@item.IsSelected"
ValueChanged="@((bool? newvalue) => OnChildSelectionChanged(parent,item,newvalue))" />
}
</Template>
</GridColumn>
<GridColumn Field="Name" Width="75px" />
<GridColumn Width="10px" Context="filecontext">
<Template>
@{
var dataSubItem = (FileName)filecontext;
@if (dataSubItem.SubData?.Any() == true)
{
<TelerikButton Icon="@GetChildButtonIcon(dataSubItem)"
FillMode="@Telerik.Blazor.ThemeConstants.Button.FillMode.Flat"
OnClick="@(() => ToggleChildExpand(dataSubItem))" />
}
}
</Template>
</GridColumn>
</GridColumns>
<DetailTemplate Context="FileInfo">
<TelerikGrid Data="FileInfo.SubData" Class="no-grid-header" Height="50px">
<GridColumns>
<GridColumn Field="FileName"></GridColumn>
</GridColumns>
</TelerikGrid>
</DetailTemplate>
</TelerikGrid>
}
}
</DetailTemplate>
<GridColumns>
<GridColumn Width="15px">
<HeaderTemplate>
@{
<TelerikCheckBox TValue="bool?" Value="@SelectAllCheckBoxValue"
TabIndex="-1"
Indeterminate="@(SelectAllCheckBoxValue == null)"
ValueChanged="@((bool? value) => ValueChanged(value))" />
}
</HeaderTemplate>
<Template>
@{
var item = (FileList)context;
<TelerikCheckBox Value="@item.IsSelected" ValueChanged="@((bool? newvalue)=> OnParentSelectionChanged(item,newvalue))" Indeterminate="@(item.IsSelected == null)" />
}
</Template>
</GridColumn>
<GridColumn Field="@nameof(FileList.Name)" Title="Name" Width="75px" />
<GridColumn Field="@nameof(FileList.Size)" Title="Size" Width="35px" />
<GridColumn Width="10px">
<Template>
@{
var dataItem = (FileList)context;
@if (dataItem.SubData?.Any() == true)
{
<TelerikButton Icon="@GetButtonIcon(dataItem)"
FillMode="@Telerik.Blazor.ThemeConstants.Button.FillMode.Flat"
OnClick="@( () => ToggleExpand(dataItem) )" />
}
}
</Template>
</GridColumn>
</GridColumns>
</TelerikGrid>
<style>
.no-grid-header .k-grid-header {
display: none;
}
/* hide grid row separator */
.no-row-border tbody tr td {
border-bottom: none !important;
}
/* shrink the hierarchy column - do not hide it completely */
.no-default-hierarchy-column .k-hierarchy-col {
width: 0;
}
/* hide everything in the hierarchy column */
.no-default-hierarchy-column .k-hierarchy-cell * {
display: none;
}
</style>
@code {
private List<FileList> fileLists = new List<FileList>();
private List<SubFileName> subFileNames1 = new List<SubFileName>();
private List<SubFileName> subFileNames2 = new List<SubFileName>();
private new List<FileName> fileNames = new List<FileName>();
private TelerikGrid<FileList>?FileListGrid;
private bool? SelectAllCheckBoxValue = false;
protected override void OnInitialized()
{
// Sample data for SubFileName
subFileNames1 = new List<SubFileName>
{
new SubFileName(1, 101, "SubFile_A1"),
new SubFileName(2, 101, "SubFile_A2")
};
subFileNames2 = new List<SubFileName>
{
new SubFileName(3, 102, "SubFile_B1"),
new SubFileName(4, 102, "SubFile_B2")
};
// Sample data for FileName
fileNames = new List<FileName>
{
new FileName( 101, 1001, "MainFile_A", subFileNames1),
new FileName( 102, 1001, "MainFile_B", subFileNames2)
};
// Sample data for FileList
fileLists = new List<FileList>
{
new FileList(1001, "FileList_1", "25MB", fileNames)
};
UpdateSelectAllValue();
}
private void ValueChanged(bool? value)
{
bool isSelected = value == true;
SelectAllCheckBoxValue = isSelected;
fileLists.ForEach(parent =>
{
parent.IsSelected = isSelected;
parent.SubData.ForEach(child => child.IsSelected = isSelected);
});
}
private async Task ToggleExpand(FileList dataItem)
{
var gridState = FileListGrid!.GetState();
if (gridState.ExpandedItems.Contains(dataItem))
{
gridState.ExpandedItems.Remove(dataItem);
}
else
{
gridState.ExpandedItems.Add(dataItem);
}
await FileListGrid.SetStateAsync(gridState);
}
private void OnParentSelectionChanged(FileList parent, bool? isSelected)
{
parent.IsSelected = isSelected;
foreach (var child in parent.SubData)
{
child.IsSelected = isSelected;
}
UpdateSelectAllValue();
}
private void UpdateSelectAllValue()
{
var parentStates =fileLists.Select(p => p.IsSelected).Distinct().ToList();
SelectAllCheckBoxValue = parentStates.Count switch
{
0 => false,
1 => parentStates[0], // All same value (true or false)
_ => null // Mixed values => indeterminate
};
}
private HashSet<FileName> ExpandedFileNames = new();
private void ToggleChildExpand(FileName file)
{
if (ExpandedFileNames.Contains(file))
ExpandedFileNames.Remove(file);
else
ExpandedFileNames.Add(file);
// FileListGrid?.Rebind();
}
private ISvgIcon GetChildButtonIcon(FileName file)
{
return ExpandedFileNames.Contains(file) ? SvgIcon.ChevronDown : SvgIcon.ChevronRight;
}
private ISvgIcon GetButtonIcon(FileList dataItem)
{
var gridState = FileListGrid!.GetState();
return GetButtonIcon(gridState.ExpandedItems.Contains(dataItem));
}
private ISvgIcon GetButtonIcon(bool isExpanded)
{
if (isExpanded)
{
return SvgIcon.ChevronDown;
}
else
{
return SvgIcon.ChevronRight;
}
}
private void OnChildSelectionChanged(FileList parent, FileName child, bool? isSelected)
{
parent.SubData.First(c => c == child).IsSelected = isSelected;
var allSelected = parent.SubData.All(c => c.IsSelected == true);
var noneSelected = parent.SubData.All(c => c.IsSelected == false);
parent.IsSelected = allSelected ? true : noneSelected ? false : (bool?)null;
UpdateSelectAllValue();
}
public class FileName
{
public int FileNameId { get; set; }
public int FileListId { get; set; }
public string Name { get; set; } = string.Empty;
public List<SubFileName> SubData { get; set; } = new();
public bool? IsSelected { get; set; } = true;
public bool? IsExpanded { get; set; } = false;
public FileName( int fileNameId, int fileListId, string fileName, List<SubFileName> subFileName)
{
FileNameId = fileNameId;
FileListId = fileListId;
Name = fileName;
SubData = subFileName;
}
}
public class SubFileName
{
public int SubFileNameId { get; set; }
public int FileNameId { get; set; }
public string FileName { get; set; } = string.Empty;
public SubFileName(int subfileNameId, int filenameId, string subFileName)
{
FileNameId = filenameId;
SubFileNameId = subfileNameId;
FileName = subFileName;
}
}
public class FileList
{
public int FileListId { get; set; }
public string Name { get; set; } = string.Empty;
public string Size { get; set; } = string.Empty;
public List<FileName> SubData { get; set; } = new();
public bool? IsSelected { get; set; } = true;
public bool? IsExpanded { get; set; } = false;
public FileList(int fileListId, string name, string size, List<FileName> subFileList)
{
FileListId = fileListId;
Name = name;
Size = size;
SubData = subFileList;
}
}
}