ListViewItems

ListViewItems loads the rows a ListViewDefinition describes and hands each one to your template. It renders no table, header, or toolbar, so you decide what a row looks like: cards, a settings list, or rows with their own buttons. Use ListView when you want the grid.

<ListViewItems Definition="@customers">
    <LoadingContent>
        <MudProgressLinear Indeterminate="true" />
    </LoadingContent>
    <EmptyContent>
        <MudText>No customers yet.</MudText>
    </EmptyContent>
    <ItemTemplate Context="row">
        <div class="customer-row">
            <strong>@row["Name"]</strong>
            <span>@row["City"]</span>
        </div>
    </ItemTemplate>
</ListViewItems>

@code {
    private readonly ListViewDefinition customers = new ListViewBuilder("Customer")
        .Column("Name")
        .Column("City")
        .OrderBy("Name asc")
        .Build();
}

Each row is the JsonObject the API returned. Read values by property path; Guid is always included.

Parameters

Parameter Type Default Description
Definition ListViewDefinition required Which rows to load: entity, columns, filter, order, and search.
ItemTemplate RenderFragment<JsonObject> required How one row renders.
LoadingContent RenderFragment? null Shown while the first load is in flight.
EmptyContent RenderFragment? null Shown when nothing matches.
TotalCountChanged EventCallback<int> How many rows match on the server, raised after each load.
RowsLoaded EventCallback<IReadOnlyList<JsonObject>> The rows just loaded. Not raised when virtualized.
UseVirtualization bool false Draws only the rows in view. See Long lists.
ItemSize float 50 A row's height in pixels, for virtualization.
VirtualizedOverscanCount int 20 Rows drawn beyond each edge of the viewport, for virtualization.
OrderProperty string? null The property that holds a row's position. See Reordering.

Reloading

The list reloads when the request changes: the entity, columns, filter, order, or search. It compares what the request is made of, not the definition object, so a page may rebuild its definition on every render.

A save elsewhere does not change the definition. Tell every list of that entity to reload through IEntityChangeNotifier:

EntityChangeNotifier.RefreshEntity("Customer");

Pair the list with ListViewSearchField and put its text in the definition's Search. The field waits for typing to pause, so the list asks the server once per word.

<ListViewSearchField Value="@search" ValueChanged="OnSearchChanged" Placeholder="Search customers..." />
<ListViewItems Definition="@customers">...</ListViewItems>

@code {
    private string? search;
    private ListViewDefinition customers = Build(null);

    private void OnSearchChanged(string text)
    {
        search = text;
        customers = Build(text);
    }

    private static ListViewDefinition Build(string? search) =>
        new ListViewBuilder("Customer").Column("Name").Column("City").Search(search).Build();
}

Long lists

By default the list reads every row in one request, up to 500. A definition that matches more shows an error instead of rows. Turn on UseVirtualization for a list that can grow past a few hundred rows:

<div style="max-height: 600px; overflow-y: auto">
    <ListViewItems Definition="@orders"
                   UseVirtualization="true"
                   ItemSize="56"
                   TotalCountChanged="@(total => orderCount = total)">
        <ItemTemplate Context="row">
            <div style="height: 56px; flex-shrink: 0">@row["Number"]</div>
        </ItemTemplate>
    </ListViewItems>
</div>

The list reads the first 100 rows with the count, then reads further rows as the user scrolls to them. It draws the rows in view plus VirtualizedOverscanCount on each side; raise it if a fast scroll shows placeholders too often. A row whose window is still loading shows an animated placeholder as tall as ItemSize. To keep it working:

  • Put it in a scroll container with a fixed or maximum height.
  • Give every row the same height and pass it as ItemSize. In a flex column, set flex-shrink: 0 on rows so they keep that height.
  • Read the count from TotalCountChanged. The list never holds all its rows, so RowsLoaded is not raised.

Reordering

Set OrderProperty to the property that holds a row's position, for example Order. Rows come back in that order, and the user can drag a row to a new place. The list writes the moved row's new position back to the server, or renumbers every row when there is no gap left between two positions. A reorderable list cannot be virtualized, because a reorder can renumber every row.

SettingsList is built this way: it is the list down the left of a settings page, with an icon, a name, and the row being edited.