Radzen Master Detail Datagrid reload issue

I have noticed some issue in my DataGrid Master Detail Hierarchy component.
When I am adding/removing to existing nested item then Grid.Reload does not refreshes UI.

If I collapse and expand row detail it shows newly added nested data which means the variable object is updated correctly, however datagrid is not able to reload when adding/removing item.

If I set null to the nested item then it works fine and updates UI and show no nested item.

Also if it's null and I add 1 nested item it works fine and update UI and show new row in the nested item.

But if the nested item is not null as per the gif and I add or remove nested item then datagrid fails to update/reload.

Can you please advise what could be the issue ?
Is it on my end or Radzen Master Detail Datagrid reload issue ?

Master Detail Hierarchy update

You can check the code created by Radzen Blazor Studio Master/Detail hierarchy template for reference and compare it with your implementation.

Dear @enchev,

I have prepared a working sample on the Radzen Demo to demonstrate the issue. Can you please run the below in the demo (Blazor DataGrid Component - Hierarchy | Free UI Components by Radzen) and follow below steps to replicate issue.

  1. Expand and Select second row (Name => Clothing) Click Add Site. You will instantly see the row gets added without collapsing the row. Then click Remove Site button and you will see it will be removed in UI without any issues.

  2. Expand and Select first row (Name => Electronics) Click Add Site. The List object will update but UI will not show the second item until we collapse and expand row. Same with Remove Site the List object will update but UI will not remove the item until we collapse and expand row.

It will be really helpful if you please advise what am I doing wrong in this ?

Master Detail Hierarchy update

<RadzenStack Gap="1rem">
    <RadzenCard Variant="Variant.Outlined">
        <RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="1.5rem;" Wrap="FlexWrap.Wrap">
            <RadzenButton Text="Add Site" Click="@(args => AddSite())" />
            <RadzenButton Text="Remove Site" Click="@(args => RemoveSite())" />
        </RadzenStack>
    </RadzenCard>

    <RadzenDataGrid @ref="ProductCategoryDataGrid"
            AllowFiltering="true"
            AllowColumnResize="true"
            AllowAlternatingRows="true"
            FilterMode="FilterMode.Advanced"
            AllowSorting="true"
            AllowPaging="true"
            AllowVirtualization="true"
            PageSize="14"
            Style="padding: 10px; height: 100%; border: none; border-radius: 10px;"
            PagerHorizontalAlign="HorizontalAlign.Left"
            ShowPagingSummary="true"
            Data="@ProductCategoryListModel"
            TItem="ProductCategoryModel"
            SelectionMode="DataGridSelectionMode.Single"
            AllowColumnPicking="true"
            @bind-Value=@SelectedProductCategory>
    <Template Context="prodCategoriesSite">
        @if (prodCategoriesSite.ProductCategorySite != null && prodCategoriesSite.ProductCategorySite.Count > 0)
        {
            <RadzenDataGrid AllowColumnResize="true"
                            AllowAlternatingRows="true"
                            AllowPaging="true"
                            AllowColumnPicking="true"
                            Data="@prodCategoriesSite.ProductCategorySite"
                            TItem="ProductCategorySiteModel">
                <Columns>
                    <RadzenDataGridColumn TItem="ProductCategorySiteModel"
                                            Property="ProductCategorySite.Sites.Name"
                                            Title="Site Authorised">
                    </RadzenDataGridColumn>
            </RadzenDataGrid>
        }
    </Template>
    <Columns>
        <RadzenDataGridColumn TItem="ProductCategoryModel" Property="Name" Title="Name" Width="80px" />
        <RadzenDataGridColumn TItem="ProductCategoryModel" Property="Short_Name" Title="Short Name" Width="80px" />
    </Columns>
    </RadzenDataGrid>
    <EventConsole @ref=@console />
</RadzenStack>

@code {
    public List<ProductCategoryModel>? ProductCategoryListModel;
    public IList<ProductCategoryModel>? SelectedProductCategory {get; set;}
    private RadzenDataGrid<ProductCategoryModel>? ProductCategoryDataGrid = new() { };
    EventConsole console;

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        ProductCategoryListModel = new List<ProductCategoryModel>
        {
            new ProductCategoryModel
            {
                Product_Category_ID = Guid.NewGuid(),
                Name = "Electronics",
                Short_Name = "Elec",
                ProductCategorySite = new List<ProductCategorySiteModel>
                {
                    new ProductCategorySiteModel
                    {
                        Product_Category_Site_ID = Guid.NewGuid(),
                        Name = "Test"
                    }
                }
            },
            new ProductCategoryModel
            {
                Product_Category_ID = Guid.NewGuid(),
                Name = "Clothing",
                Short_Name = "Cloth",
                ProductCategorySite = null
            }
        };
    }

    async Task AddSite()
    {
        if(SelectedProductCategory == null) 
        {
            console.Log("Select Row First");
            return;
        }

        ProductCategorySiteModel siteAdded= new ProductCategorySiteModel
        {
            Product_Category_Site_ID = Guid.NewGuid(),
            Name = "Third Added Site"
        };

        if (SelectedProductCategory.FirstOrDefault().ProductCategorySite == null)
        {
            SelectedProductCategory.FirstOrDefault().ProductCategorySite = new List<ProductCategorySiteModel>();
        }

        SelectedProductCategory.FirstOrDefault().ProductCategorySite.Add(siteAdded);
        console.Log("Added Site Successfully");
        ProductCategoryDataGrid.Reload();
    }

    async Task RemoveSite()
    {
        if(SelectedProductCategory == null) 
        {
            console.Log("Select Row First");
            return;
        }

        if (SelectedProductCategory.FirstOrDefault().ProductCategorySite == null)
        {
            console.Log("Select Row which has atleast 1 site.");
            return;
        }

        SelectedProductCategory.FirstOrDefault().ProductCategorySite.RemoveAt(0);
        console.Log("Removed Site Successfully");
        ProductCategoryDataGrid.Reload();
    }

    public class ProductCategoryModel
    {
        public Guid? Product_Category_ID { get; set; }
        public List<ProductCategorySiteModel>? ProductCategorySite { get; set; }
        public string? Name { get; set; }
        public string? Short_Name { get; set; }
        
        public override bool Equals(object o)
        {
            var other = o as ProductCategoryModel;
            return other?.Product_Category_ID == Product_Category_ID;
        }
    }

    public class ProductCategorySiteModel
    {
        public Guid? Product_Category_Site_ID { get; set; }
        public string? Name {get; set;}

        public override bool Equals(object o)
        {
            var other = o as ProductCategorySiteModel;
            return other?.Product_Category_Site_ID == Product_Category_Site_ID;
        }
    }
}

The closing Colmns tag is missing here. In my opinion you should call Reload() for the child DataGrid not for the parent DataGrid and to do that you should have way to get references for all child grids by parent item

1 Like

Hi @enchev,

Thank you very much this has solved my problem. Following to your solution I have 2 more questions.

  1. Should I only be calling child DataGrid reload and parent will automatically update ? I have a case where I have six nested grids so whenever there is a change in any Grid should I only call reload for the last/6th child Grid ?

  2. Do you have any suggestion for getting references for all child grids by parent item ? Or any implementation in demos ?

The parent DataGrid will need refresh only if you have some displayed information related to the chid data. Nothing will be refreshed automatically.

I believe that the thread I’ve linked demonstrates exactly such approach.