Question about multiple RadzenDataGrid generated in foreach loop

Hi all,

When creating multiple instances of RadzenDataGrid in a foreach loop how do I update these grids when for example deleting a row?

In the page below I've created a button on each row that deletes the row from the model and db, but the datagrid is not updating after the Reload method execution. When I change the code in my DeleteItemDate method to add a new row, the row is added to a different DataGrid. I think this is because the grids are generated in a foreach loop without unique properties to update them on later.

How do I update the correct DataGrid?

@page "/Test/{ProjectID:int}"

@using Custom.Models;
@using Custom.DbAccess.Services
@using Radzen.Blazor

@inject NavigationManager _navigationManager
@inject ProjectService _projectService
@inject UserService _userService

<RadzenRow Style="height:100%">
        <RadzenAccordion>
            <Items>
                <RadzenAccordionItem Text="Project details" Icon="sort" Selected=true>

                    <RadzenTabs @bind-SelectedIndex=@selectedTabIndex>
                        <Tabs>

                            @foreach (var phase in project.Phases)
                            {
                                <RadzenTabsItem Text="@phase.Name">

                                    <RadzenTree  Style="width:100%">
                                        <ChildContent>

                                            @foreach (var item in phase.Items)
                                            {


                                                <RadzenTreeItem style="padding-left:0">
                                                    <Template>
                                                        <RadzenText TextStyle="TextStyle.Subtitle1">@item.Article.ArticleNumber @item.Article.Description</RadzenText>
                                                    </Template>

                                                    <ChildContent>

                                                        <RadzenDataGrid @ref="dataGrid" Data="@item.ItemDates" >
                                                            <Columns>
                                                                <RadzenDataGridColumn Property="Appointment.StartDate" Title="Start date" />
                                                                <RadzenDataGridColumn Property="Appointment.User.Fullname" Title="Consultant" />
                                                                <RadzenDataGridColumn Property="ItemDateDescription" Title="Description" />

                                                                <RadzenDataGridColumn Title="Actions">
                                                                    <Template Context="data">
                                                                        <RadzenButton Click=@(() => DeleteItemDate(data, dataGrid, item)) Icon="clear" IconColor="#E4572E"></RadzenButton>
                                                                    </Template>
                                                                </RadzenDataGridColumn>

                                                            </Columns>
                                                        </RadzenDataGrid>
                                                    </ChildContent>

                                                </RadzenTreeItem>
                                            }

                                        </ChildContent>
                                    </RadzenTree>
                                </RadzenTabsItem>
                            }

                        </Tabs>
                    </RadzenTabs>
                </RadzenAccordionItem>
            </Items>
        </RadzenAccordion>
</RadzenRow>


@code
{
    [Parameter] public int ProjectID { get; set; }
    private Project? project;
    private IEnumerable<ProjectStatus>? statusList;
    private IEnumerable<User>? userList;
    int selectedTabIndex = 0;
    RadzenDataGrid<ItemDate> dataGrid;

    private async void Update()
    {
        await _projectService.UpdateProject(project);
    }

    private void DeleteItemDateFromDb(ItemDate itemDate)
    {
        _projectService.DeleteItemDate(itemDate);
    }

    private async void DeleteItemDate(ItemDate itemDate, RadzenDataGrid<ItemDate> gridToUpdate, PhaseItem itemToUpdate)
    {

        //Remove itemDate from Item model
        itemToUpdate.ItemDates.Remove(itemDate);

        //Remove itemDate from database
        DeleteItemDateFromDb(itemDate);

        //Refresh this specific instance of the datagrid that shows itemdates + appointments
        await gridToUpdate.Reload();
    }


    protected override async Task OnInitializedAsync()
    {
        //Get project details
        project = await _projectService.GetProjectByIdAsync(ProjectID);

        //Get list of all available project statusses
        statusList = await _projectService.GetProjectStatusList();

        //Get list of all available users
        userList = await _userService.GetAllVisibleUsersAsync();


    }
}




You can bind them for example to ObservableCollection.

That sounds like an option, could you maybe elaborate a bit more on how to do this?

Wrap this in ObservableColection.

I'm trying to learn how this should work, but because these DataGrids are inside a foreach that on it's own are also inside a different foreach loop I don't know how to implement this. Could you copy my code and alter to your suggestion?

Hi @nunile,

No, we don't do that.

I suggest checking the ObservableCollection documentation. This stackoverflow thread could also be of help: c# - What is the use of ObservableCollection in .net? - Stack Overflow

Thank you for the pointers! after reading the suggested docs I was able to get it working by using:

Data="new ObservableCollection<ItemDate>(item.ItemDates)"

I also changed the method that is called by the button because I noticed that I don't need to explicitly Reload the grid, it happens automatically:

Click=@(() => DeleteItemDate(data, item))

private async void DeleteItemDate(ItemDate itemDate, PhaseItem itemToUpdate)
{
    //Remove itemDate from Item model
    itemToUpdate.ItemDates.Remove(itemDate);

    //Remove itemDate from database
    DeleteItemDateFromDb(itemDate); 
}

Could you please confirm that this is in fact the suggested way, or did I miss something here? I also would like to know how the DataGrid knows to update the UI. Is it purely because the data now holds an ObservableCollection? Or how does this exactly work?

Again, many thanks for the quick responses and tips :slight_smile:

Yes, if you need all the details check the source.