How to make a generic DataGrid using RenderFragment

I have been trying several times now to use the DataGrid example from the website, and create a generic component so that the functionality in that can be reproduced and contained in the usecase of having several tables for simple data CRUD. I can not get it to work and it's becomming a huge frustration point. Can anyone take a look at this and tell me what am I missing? It's almost working appart from the fact that the render fragment itself is not being rendered for whatever reason.

I am aiming for something like this:

<DataGrid TItem="CategoryDtO"
          GetItems="@GetItems"
          SendCreateItemCommand="@SendCreateItemCommand"
          SendDeleteItemCommand="@SendDeleteItemCommand"
          SendUpdateItemCommand="@SendUpdateItemCommand">
    
    <RowTemplate Context="category">
        <RadzenDataGridColumn TItem="CategoryDtO" Title="Name" Property="@category.Name">
            <EditTemplate>
                <RadzenTextBox @bind-Value="@category.Name" />
            </EditTemplate>
        </RadzenDataGridColumn>
    </RowTemplate>

</DataGrid>

@code
{

    [Inject] public IMediator Mediator { get; set; }
    [Parameter] public Guid BudgetSheetId { get; set; }

    public async Task<IEnumerable<CategoryDtO>> GetItems()
    {
        var cts = new CancellationTokenSource();
        var token = cts.Token;
        var command = new GetBudgetSheetCategories { BudgetSheetId = BudgetSheetId };
        var result = await Mediator.Send(command, token);
        return result;
    }

    public async Task<bool> SendCreateItemCommand(CategoryDtO item)
    {
        var cts = new CancellationTokenSource();
        var token = cts.Token;
        var command = new CreateBudgetSheetCategory { BudgetSheetId = BudgetSheetId, CategoryName = item.Name};
        var result = await Mediator.Send(command, token);
        return result;
    }

    public async Task<bool> SendDeleteItemCommand(CategoryDtO item)
    {
        var cts = new CancellationTokenSource();
        var token = cts.Token;
        var command = new DeleteBudgetSheetCategory { BudgetSheetId = BudgetSheetId, CategoryName = item.Name };
        var result = await Mediator.Send(command, token);
        return result;
    }

    public async Task<bool> SendUpdateItemCommand(CategoryDtO item)
    {
        // var cts = new CancellationTokenSource();
        // var token = cts.Token;
        // var command = new UpdateBudgetSheetCategory { BudgetSheetId = BudgetSheetId, CategoryName = item.Name };
        // var result = await Mediator.Send(command, token);
        // return result;
        throw new NotImplementedException();
    }
}

In the above component, I inherig the DataGrid that I make, then I can pass on a function for each of the basic crud actions, as well as a RenderFragment that applies to the type parameter for rendering each row.

For the DataGrid component I have the following markup:

@typeparam TItem where TItem : new()

<style>
    .rz-grid-table {
        width: unset;
    }
</style>


<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="10px" class="mt-2 mb-4">
    <RadzenButton ButtonStyle="ButtonStyle.Success" Icon="add_circle_outline" Text="Add New Order" Click="@InsertRow"/>
</RadzenStack>

<RadzenDataGrid @ref="itemsGrid" AllowAlternatingRows="false" AllowFiltering="true" AllowPaging="true" PageSize="5" AllowSorting="true" EditMode="DataGridEditMode.Single"
                Data="@Model.items" TItem="TItem" RowUpdate="@OnUpdateRow" RowCreate="@OnCreateRow" Sort="@Reset" Page="@Reset" Filter="@Reset" ColumnWidth="200px">
    <Columns>
        @foreach (var item in Model.items)
        {
            @RowTemplate(item)
        }
    </Columns>
</RadzenDataGrid>

Here is where I have the code from the data grid example on the webpage, difference being I use the RowTemplate render fragment to populate the columns element.

Then in the codebehind file I have the partial class and the table model:


public class DataGridModel<TItem>
{
    internal IEnumerable<TItem> items { get; set; } = new List<TItem>();
    public List<TItem> ItemsToInsert { get; set; } = new List<TItem>();
    public List<TItem> ItemsToUpdate { get; set; } = new List<TItem>();
}

public partial class DataGrid<TItem> : ComponentBase where TItem : new()
{
    [Inject] public IMediator Mediator { get; set; }
    
    [Parameter] public required Func<TItem, Task> SendCreateItemCommand { get; set; }
    [Parameter] public required Func<TItem, Task> SendUpdateItemCommand { get; set; }
    [Parameter] public required Func<TItem, Task> SendDeleteItemCommand { get; set; }
    
    // Parameter functions for getting the data
    [Parameter] public required Func<Task<IEnumerable<TItem>>> GetItems { get; set; }
    
    [Parameter] public RenderFragment<TItem> RowTemplate { get; set; }


    protected RadzenDataGrid<TItem> itemsGrid;
    protected DataGridModel<TItem?> Model = new DataGridModel<TItem?>();

    protected void Reset()
    {
        Guard.Against.Null(Model, nameof(Model));
        Model.ItemsToInsert.Clear();
        Model.ItemsToUpdate.Clear();
    }

    protected void Reset(TItem? item)
    {
        Guard.Against.Null(Model, nameof(Model));
        Model.ItemsToInsert.Remove(item);
        Model.ItemsToUpdate.Remove(item);
    }

    protected override async Task OnInitializedAsync()
    {
        Guard.Against.Null(Mediator, nameof(Mediator));
        await base.OnInitializedAsync();
        await LoadData();
    }
    
    private async Task LoadData()
    {
        Model.items = await GetItems();
    }

    private async Task ReloadGrid()
    {
        await LoadData();
        await itemsGrid.Reload();
    }

    protected async Task EditRow(TItem? item)
    {
        if (Model.ItemsToInsert.Count() > 0)
        {
            Reset();
        }

        Model.ItemsToUpdate.Add(item);
        await itemsGrid.EditRow(item);
    }
    
    protected async void OnUpdateRow(TItem item)
    {
        Reset(item);
        await SendUpdateItemCommand(item);
        await ReloadGrid();
    }

    protected async Task SaveRow(TItem item)
    {
        await itemsGrid.UpdateRow(item);
    }

    protected void CancelEdit(TItem? item)
    {
        Reset(item);
        itemsGrid.CancelEditRow(item);
    }

    protected async Task DeleteRow(TItem? item)
    {
        Reset(item);

        if (Model.items.Contains(item))
        {
            await SendDeleteItemCommand(item);
            await ReloadGrid();
        }
        else
        {
            itemsGrid.CancelEditRow(item);
            await ReloadGrid();
        }
    }

    protected async Task InsertRow()
    {
        Reset();
        
        var item = new TItem();
        Model.ItemsToInsert.Add(item);
        await itemsGrid.InsertRow(item);
    }

    protected async Task OnCreateRow(TItem? item)
    {
        await SendCreateItemCommand(item);
        Model.ItemsToInsert.Remove(item);
    }
}

Here I have the same code from the example, but I replace the direct db calls with calls to the separate Func items, that are passed on as parameters when the table is instantiated.

When I try to render the table however, nothing is rendered. Any clues as to why? I had a similar setup working through a regular html table, so I would be curious if there's something Razor specific that prevents this from happening?