No empty text when LoadData event callback is set

According to your example at Empty Data Grid. With LoadData set - no empty text. Even if LoadData makes nothing.

@using RadzenBlazorDemos.Models.Northwind

<RadzenDataGrid TItem="Employee" Data="@data" LoadData="@LoadData">
    <Columns>
        <RadzenDataGridColumn TItem="Employee" Property="FirstName" Title="First Name" />
        <RadzenDataGridColumn TItem="Employee" Property="LastName" Title="Last Name" />
    </Columns>
</RadzenDataGrid>   

@code { 
    List<Employee> data = new List<Employee>();
    
    void LoadData(LoadDataArgs args)
    {}
}

Just remove LoadData="@LoadData", and empty text appears again. Default empty text, custom empty text, template for empty text - it all relates to the same issue.

When using LoadData you need to set Count.

Anyway it doesn't work even like these two variants - updating count field at initialization or at LoadData event callback. Just removing LoadData="@LoadData" makes it work for both variants.

@using RadzenBlazorDemos.Models.Northwind

<RadzenDataGrid TItem="Employee" Data="@data" LoadData="@LoadData" Count=@count>
    <Columns>
        <RadzenDataGridColumn TItem="Employee" Property="FirstName" Title="First Name" />
        <RadzenDataGridColumn TItem="Employee" Property="LastName" Title="Last Name" />
    </Columns>
</RadzenDataGrid>   

@code { 
    List<Employee> data = new List<Employee>();
    int count;
    
    protected override void OnInitialized()
    {
        base.OnInitialized();        
        count = data.Count;
    }
    
    void LoadData(LoadDataArgs args)
    {}
}
@using RadzenBlazorDemos.Models.Northwind

<RadzenDataGrid TItem="Employee" Data="@data" LoadData="@LoadData" Count=@count>
    <Columns>
        <RadzenDataGridColumn TItem="Employee" Property="FirstName" Title="First Name" />
        <RadzenDataGridColumn TItem="Employee" Property="LastName" Title="Last Name" />
    </Columns>
</RadzenDataGrid>   

@code { 
    List<Employee> data = new List<Employee>();
    int count; 
    
    void LoadData(LoadDataArgs args)
    {
        count = data.Count;
    }
}

Count is 0 here. You can check carefully our demo for LoadData binding - it should be set to total records count.

I don't understand. If I want to show the empty data grid, then the count should be 0 anyway, isn't it? If the count wouldn't be 0, the empty text couldn't be displayed, right? I can't see any situations when I can show empty text and set LoadData callback at the same time.

Another approach, based on your LoadData example. I've just copied the code from there and simplified it. Now we have only two columns that are allowed to filter. Added the display for "count" variable to check it. Now try to filter the data so there will be 0 results - for example, filter by first name with "ddd" value. With 0 results you can't obtain the value of empty text property in the data grid.

@using System.Linq.Dynamic.Core
@using RadzenBlazorDemos.Data
@using RadzenBlazorDemos.Models.Northwind

@inherits DbContextPage

<p>@count</p>
<RadzenDataGrid 
    Count="@count" 
    Data="@employees" 
    LoadData="@LoadData" 
    AllowFiltering="true"
    TItem="Employee"
    EmptyText="AAAAAAAA"
    ColumnWidth="200px">
    <Columns>
        <RadzenDataGridColumn TItem="Employee" Property="EmployeeID" Title="ID" />
        <RadzenDataGridColumn TItem="Employee" Property="FirstName" Title="First Name" />
    </Columns>
</RadzenDataGrid>

@code {
    int count;
    IEnumerable<Employee> employees;

    async Task LoadData(LoadDataArgs args)
    {
        var query = dbContext.Employees.AsQueryable();

        if (!string.IsNullOrEmpty(args.Filter))
            query = query.Where(args.Filter);
        
        count = query.Count();
        employees = query.Skip(args.Skip.Value).Take(args.Top.Value).ToList();
    }
}

You can set AllowPaging to true. Your Data also needs to be an empty collection not null.

@using System.Linq.Dynamic.Core
@using RadzenBlazorDemos.Data
@using RadzenBlazorDemos.Models.Northwind

<RadzenDataGrid Count="@count" AllowPaging=true
                Data="@employees"
                LoadData="@(args => { })"
                AllowFiltering="true"
                TItem="Employee"
                EmptyText="No records"
                ColumnWidth="200px">
    <Columns>
        <RadzenDataGridColumn TItem="Employee" Property="EmployeeID" Title="ID" />
        <RadzenDataGridColumn TItem="Employee" Property="FirstName" Title="First Name" />
    </Columns>
</RadzenDataGrid>

@code {
    int count;
    IEnumerable<Employee> employees = Enumerable.Empty<Employee>();
}

Strangely - it works with LoadData from my example with

AllowPaging=true

and null for employees at start (after first loading it calls LoadData of course and fill the employees collection)

IEnumerable<Employee> employees;

But if I want virtualization instead of paging? If I disable paging and allow virtualization

AllowVirtualization="true"

then no EmptyText is shown.

It seems like it is easier to show my own empty text somewhere above the data grid, like this (used my own simple class to demonstrate the example, added some test variables to check virtualization):

@using System.Linq.Dynamic.Core

<p>@count</p>
<p>@skip</p>
<p>@take</p>
<p>@emptyText</p>
<RadzenDataGrid 
    Count="@count" 
    Data="@toShow" 
    LoadData="@LoadData" 
    AllowFiltering="true"
    TItem="My"
    ColumnWidth="200px"
    style="height: 300px"
    AllowVirtualization="true">
    <Columns>
        <RadzenDataGridColumn TItem="My" Property="Id" Title="Id" />
    </Columns>
</RadzenDataGrid>

@code {
    int count;
    int skip;
    int take;
    string emptyText;
    IEnumerable<My> toShow;
    IEnumerable<My> source = Enumerable.Range(0, 100).Select(id => new My() { Id = id });

    async Task LoadData(LoadDataArgs args)
    {
        var query = source.AsQueryable();

        if (!string.IsNullOrEmpty(args.Filter))
            query = query.Where(args.Filter);
        
        count = query.Count();
        emptyText = count > 0 ? string.Empty : "NO RECORDS";
        skip = args.Skip.Value;
        take = args.Top.Value;
        toShow = query.Skip(args.Skip.Value).Take(args.Top.Value).ToList();        
    }
    
    public class My { public int Id {get ;set; } }
}

Some additional question here - it seems like LoadDataArgs.Take is assigned inside data grid according to the allowed space for data inside the table? Can I assign it directly to reduce the number of calls to the source - to get the data at each source call with some reserve, enough to show them inside the table while scrolling? Of cource I need to take into account the table height, but this is up to me.

In case of virtualization Virtualize component is used internally and this component will provide the data for DataGrid LoadDataArgs:

Thank you. So, it is easier for me to stay with virtualization with auto "Take".

Found out! This was in one of your recent updates: VirtualizationOverscanCount. Now it is much better )))

@using System.Linq.Dynamic.Core

<p>@count</p>
<p>@skip</p>
<p>@take</p>
<p>@emptyText</p>
<RadzenDataGrid 
    Count="@count" 
    Data="@toShow" 
    LoadData="@LoadData" 
    AllowFiltering="true"
    TItem="My"
    ColumnWidth="200px"
    style="height: 300px"
    AllowVirtualization="true"
    VirtualizationOverscanCount=10>
    <Columns>
        <RadzenDataGridColumn TItem="My" Property="Id" Title="Id" />
    </Columns>
</RadzenDataGrid>

@code {
    int count;
    int skip;
    int take;
    string emptyText;
    IEnumerable<My> toShow;
    IEnumerable<My> source = Enumerable.Range(0, 100).Select(id => new My() { Id = id });

    async Task LoadData(LoadDataArgs args)
    {
        var query = source.AsQueryable();

        if (!string.IsNullOrEmpty(args.Filter))
            query = query.Where(args.Filter);
        
        count = query.Count();
        emptyText = count > 0 ? string.Empty : "NO RECORDS";
        skip = args.Skip.Value;
        take = args.Top.Value;
        toShow = query.Skip(args.Skip.Value).Take(args.Top.Value).ToList();        
    }
    
    public class My { public int Id {get ;set; } }
}