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");
Search
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, setflex-shrink: 0on rows so they keep that height. - Read the count from
TotalCountChanged. The list never holds all its rows, soRowsLoadedis 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.