ListView
Since 0.1.0-alpha.20Static server-side rendering: no circuit, no WebAssembly.
A list of items from data, each drawn by a template: contacts, notifications, files, results. The list sibling of Table: the same Items or ItemsProvider, ItemKey and paging, with one template per item instead of columns.
Usage
<ListView Items="people" ItemKey="p => p.Id" ItemHref="(p => $"/people/{p.Id}")" Context="person">
<Avatar Name="person.Name" /> person.Name
</ListView>Links and the current item
Use ItemText, ItemDescription and ItemIcon for a row with no template, ItemHref to make each item a link, and ItemCurrent for the one the page is showing.
Preview
- Ada LovelaceAda Lovelaceada@example.com
- Grace HopperGrace Hoppergrace@example.com
- Alan TuringAlan Turingalan@example.com
- Katherine JohnsonKatherine Johnsonkatherine@example.com
Code
@* Each contact links to this page with ?contact=, and the one in the address is current: a list
beside its details that works in every mode, with no script. (A link's address is resolved
against the page's <base href>, so it's built whole, not as a bare "?contact=".) *@
NavigationManager Navigation
<ListView Items="_people" ItemKey="p => p.Id" ItemText="p => p.Name" ItemDescription="p => p.Email"
ItemIcon="_ => Lucide.CircleUser" ItemHref="(p => Navigation.GetUriWithQueryParameter("contact", p.Id))" ItemCurrent="p => p.Id == Contact"
Bordered MaxWidth="24.Rem" />
{
[SupplyParameterFromQuery] private string? Contact { get; set; }
private readonly Person[] _people =
[
new("ada", "Ada Lovelace", "ada@example.com"),
new("grace", "Grace Hopper", "grace@example.com"),
new("alan", "Alan Turing", "alan@example.com"),
new("katherine", "Katherine Johnson", "katherine@example.com"),
];
}Selection
Use SelectionMode for a checkbox per item (or a radio button, for one), and SelectAllMode for whether its select-all takes the page or every match: inside a form the selected items post their ItemKey as a Selection, and @bind-Selection follows them on interactive pages. With script, a checkbox above the list selects the page.
Preview
Code
@* Selection in a form: each checked item posts its ItemKey, so Archive works with JavaScript off.
With script, "Select all messages" above the list checks the page. Archived messages leave the
list; on static pages hidden fields carry them to the next post. *@
<form method="post" @onsubmit="Submit" @formname="list-view-archive" style="width: 100%">
<AntiforgeryToken />
foreach (var id in _archived)
{
<input type="hidden" name="archived" value="id" />
}
<Stack Gap="3" MaxWidth="28.Rem">
<ListView Items="Inbox" ItemKey="m => m.Id" ItemText="m => m.Subject" ItemDescription="m => m.From"
SelectionMode="SelectionMode.Multiple" SelectAllLabel="Select all messages" @bind-Selection="_selected" EmptyText="Nothing left in the inbox." Bordered />
<Row Gap="3" Align="Align.Center" Wrap>
<Button Submit Variant="ButtonVariant.Outline" Accent="Accent.Neutral" StartIcon="Lucide.Archive" Disabled="Inbox.Count == 0">Archive selected</Button>
if (_archived.Count > 0)
{
<Button Submit Name="restore" Value="all" OnClick="() => _restoring = true" Variant="ButtonVariant.Ghost" Accent="Accent.Neutral">Restore all</Button>
}
<TextBlock Size="TextSize.Sm" Color="Color.Muted" role="status">_status</TextBlock>
</Row>
</Stack>
</form>
{
// Static pages: the checked items post as "selected", and the ones archived before as "archived".
[SupplyParameterFromForm(FormName = "list-view-archive", Name = "selected")]
private Selection? Posted { get; set; }
[SupplyParameterFromForm(FormName = "list-view-archive", Name = "archived")]
private string[]? PostedArchived { get; set; }
[SupplyParameterFromForm(FormName = "list-view-archive", Name = "restore")]
private string? PostedRestore { get; set; }
// Interactive pages: bound to the checkboxes; Restore all says it was pressed.
private Selection? _selected;
private bool _restoring;
private HashSet<string> _archived = [];
private string? _status;
private readonly Message[] _messages =
[
new("1", "Quarterly report draft", "Grace Hopper"),
new("2", "Lunch on Friday?", "Alan Turing"),
new("3", "Build failed on main", "CI"),
new("4", "Invoice #1042", "Billing"),
];
private List<Message> Inbox => _messages.Where(m => !_archived.Contains(m.Id)).ToList();
protected override void OnInitialized()
{
_archived = [.. PostedArchived ?? []];
_selected = Posted;
}
private void Submit()
{
if (PostedRestore is not null || _restoring)
{
_restoring = false;
_archived.Clear();
_status = "Restored every message.";
}
else
{
var picked = (Posted ?? _selected ?? Selection.None).Apply(Inbox.AsQueryable(), m => m.Id).ToList();
_archived.UnionWith(picked.Select(m => m.Id));
_status = picked.Count switch
{
0 => "Select the messages to archive first.",
1 => $"Archived \"{picked[0].Subject}\".",
_ => $"Archived {picked.Count} messages.",
};
}
_selected = Selection.None;
}
}Actions on items
Use ItemActions for content at each item's end, such as a badge or an icon button named for its item, and ItemMenu for a ⋯ menu of MenuItems, named "Actions for" and the item's label. Keep one or two actions visible and put the rest in the menu; a menu that renders nothing for an item leaves it without the button.
Preview
Code
@* Each button posts its Name=Value with the form, so the actions work with JavaScript off;
OnClick says which it was on interactive pages, where nothing posts. A file shared with you
has no Delete, so its menu is shorter. *@
<form method="post" @onsubmit="Act" @formname="list-view-files" style="width: 100%">
<AntiforgeryToken />
<Stack Gap="3" MaxWidth="32.Rem">
<ListView Items="_files" ItemKey="f => f.Id" ItemText="f => f.Name" ItemDescription="f => f.Detail" ItemIcon="_ => Lucide.FileText" Bordered Context="file">
<ItemActions>
if (file.Shared)
{
<Badge>Shared</Badge>
}
<IconButton Icon="Lucide.Star" Label="($"Star {file.Name}")" Submit Name="intent" Value="($"star:{file.Id}")"
OnClick="(() => _clicked = $"star:{file.Id}")" Variant="ButtonVariant.Ghost" Accent="Accent.Neutral" Size="ControlSize.Sm" />
</ItemActions>
<ItemMenu>
<MenuItem Submit Name="intent" Value="($"download:{file.Id}")" OnClick="(() => _clicked = $"download:{file.Id}")" Icon="Lucide.Download">Download</MenuItem>
<MenuItem Submit Name="intent" Value="($"archive:{file.Id}")" OnClick="(() => _clicked = $"archive:{file.Id}")" Icon="Lucide.Archive">Archive</MenuItem>
if (!file.Shared)
{
<MenuDivider />
<MenuItem Submit Name="intent" Value="($"delete:{file.Id}")" OnClick="(() => _clicked = $"delete:{file.Id}")" Icon="Lucide.Trash" Accent="Accent.Danger">Delete</MenuItem>
}
</ItemMenu>
</ListView>
<TextBlock Size="TextSize.Sm" Color="Color.Muted" role="status">_done</TextBlock>
</Stack>
</form>
{
// Static pages: the pressed button's Name=Value posts with the form.
[SupplyParameterFromForm(FormName = "list-view-files", Name = "intent")]
private string? Posted { get; set; }
// Interactive pages post nothing, so OnClick says which button it was.
private string? _clicked;
private string? _done;
private readonly FileEntry[] _files =
[
new("1", "Quarterly report.pdf", "2.4 MB, edited today"),
new("2", "Brand guidelines.pdf", "8.1 MB, shared by Grace", Shared: true),
new("3", "Budget 2027.xlsx", "640 KB, edited Monday"),
];
private void Act()
{
var (verb, id) = (Posted ?? _clicked)?.Split(':', 2) is [var v, var i] ? (v, i) : (null, null);
_clicked = null;
var done = verb switch { "star" => "Starred", "download" => "Downloaded", "archive" => "Archived", "delete" => "Deleted", _ => null };
if (done is not null && _files.FirstOrDefault(f => f.Id == id) is { } file)
{
_done = $"{done} {file.Name}.";
}
}
}Static: The same posts; the menu has arrow keys and type-ahead.
Cards in columns
Use Columns to lay the items out as cards, such as a gallery of products: that many across from 640px up, one on phones. With ItemHref each card is a link, and controls inside it still work.
Preview
- Standing desk
Standing desk
NewOak top, quiet motor, three memory positions.
$549.00
- Task chair
Task chair
Mesh back with adjustable lumbar support.
$329.00
- Desk lamp
Desk lamp
Warm to cool light, dims to 5%.
$79.00
- Monitor arm
Monitor arm
Holds screens up to 32 inches.
$119.00
- Standing mat
Standing mat
NewCushioned, with beveled edges.
$59.00
- Wall shelf
Wall shelf
Floating, holds 20 kg.
$89.00
Code
@* Columns lays the items out as cards, three across from 640px up and one on phones. Each card
links to this page with ?product=, and the chosen one is current. *@
NavigationManager Navigation
<ListView Items="_products" ItemKey="p => p.Sku" ItemLabel="p => p.Name" ItemHref="(p => Navigation.GetUriWithQueryParameter("product", p.Sku))"
ItemCurrent="p => p.Sku == Product" Columns="3" Context="product">
<Stack Gap="1">
<Row Justify="Justify.Between" Align="Align.Center">
<Heading Level="3" Size="TextSize.Md">product.Name</Heading>
if (product.New)
{
<Badge Accent="Accent.Primary">New</Badge>
}
</Row>
<TextBlock Size="TextSize.Sm" Color="Color.Muted">product.Description</TextBlock>
<TextBlock Weight="FontWeight.Semibold">product.Price.ToString("C", System.Globalization.CultureInfo.GetCultureInfo("en-US"))</TextBlock>
</Stack>
</ListView>
{
[SupplyParameterFromQuery] private string? Product { get; set; }
private readonly Item[] _products =
[
new("desk", "Standing desk", "Oak top, quiet motor, three memory positions.", 549m, New: true),
new("chair", "Task chair", "Mesh back with adjustable lumbar support.", 329m),
new("lamp", "Desk lamp", "Warm to cool light, dims to 5%.", 79m),
new("arm", "Monitor arm", "Holds screens up to 32 inches.", 119m),
new("mat", "Standing mat", "Cushioned, with beveled edges.", 59m, New: true),
new("shelf", "Wall shelf", "Floating, holds 20 kg.", 89m),
];
}Load more
Use PageSize with DataPaging.LoadMore for a button after the last item that adds the next page, and MaxHeight to scroll the items in the list's box, the button with them. Numbered pages and DataPaging.NextPrevious work as in Table. The page goes in the address, so QueryPrefix keeps two lists apart.
Preview
- Notification 17 minutes ago
- Notification 214 minutes ago
- Notification 321 minutes ago
- Notification 428 minutes ago
Code
@* PageSize with Paging="DataPaging.LoadMore": the first page, and a button after it that adds
the next, scrolling with the items in a box as tall as MaxHeight. On static pages and with
JavaScript off, the button is a link to the same list with one more page. *@
<ListView Items="_events" ItemKey="e => e.Id" ItemText="e => e.Title" ItemDescription="e => e.When"
ItemIcon="_ => Lucide.Bell" PageSize="4" Paging="DataPaging.LoadMore" QueryPrefix="events-"
MaxHeight="16.Rem" Bordered AriaLabel="Notifications" MaxWidth="28.Rem" Grow />
{
private readonly Event[] _events = Enumerable.Range(1, 11)
.Select(i => new Event(i.ToString(System.Globalization.CultureInfo.InvariantCulture), $"Notification {i}", $"{i * 7} minutes ago"))
.ToArray();
}Static: The same link; enhanced navigation swaps the list in, with focus on the first new item.
Loading on scroll
Use DataPaging.LoadOnScroll with a MaxHeight: the next page loads as the last item scrolls into view. Its Load more button is for the keyboard, out of sight until it has focus.
Preview
- Message 13 minutes ago
- Message 26 minutes ago
- Message 39 minutes ago
- Message 412 minutes ago
- Message 515 minutes ago
- Message 618 minutes ago
- Message 721 minutes ago
- Message 824 minutes ago
Code
@* PageSize with Paging="DataPaging.LoadOnScroll" and a MaxHeight: the next page loads as the
last item scrolls into view, on interactive pages. *@
<ListView Items="_messages" ItemKey="m => m.Id" ItemText="m => m.Title" ItemDescription="m => m.When"
ItemIcon="_ => Lucide.MessageSquare" PageSize="8" Paging="DataPaging.LoadOnScroll" QueryPrefix="feed-"
MaxHeight="18.Rem" Bordered AriaLabel="Messages" MaxWidth="28.Rem" Grow />
{
private readonly Message[] _messages = Enumerable.Range(1, 40)
.Select(i => new Message(i.ToString(System.Globalization.CultureInfo.InvariantCulture), $"Message {i}", $"{i * 3} minutes ago"))
.ToArray();
}Static: Scroll the list: the next page loads as the last item comes into view, by the Load more link, which enhanced navigation swaps in with the scroll kept.
Reordering, and saving the order
Use Reorderable. On a static page give it a Name and pass the posted ListOrder back as Order; Order.Arrange puts the items in the posted order. On an interactive page, @bind-Items keeps the order.
Preview
Code
@* On a static page the list posts with its form: Order holds the posted keys and any menu move,
and the list shows them. Save arranges the steps when the form's own button posted. *@
<Stack Gap="3" MaxWidth="24.Rem" Grow>
<Form Model="this" FormName="list-view-steps" OnValidSubmit="Save">
<ListView @bind-Items="_steps" ItemKey="s => s.Id" ItemText="s => s.Title" Reorderable Name="order" Order="Order" Bordered />
<FormActions><Button Submit>Save order</Button></FormActions>
</Form>
if (_saved is not null)
{
<TextBlock Size="TextSize.Sm" Color="Color.Muted">_saved</TextBlock>
}
</Stack>
{
[SupplyParameterFromForm(FormName = "list-view-steps", Name = "order")]
private ListOrder? Order { get; set; }
private IReadOnlyList<Step> _steps = [new("1", "Draft"), new("2", "Review"), new("3", "Approve"), new("4", "Publish")];
private string? _saved;
private void Save()
{
// A menu move posts too; only the Save button saves.
if (Order?.Move is not null)
{
return;
}
if (Order is not null)
{
_steps = Order.Arrange(_steps, s => s.Id);
}
_saved = $"Saved: {string.Join(", ", _steps.Select(s => s.Title))}.";
}
}Static: Drag a handle, or use its menu or Alt+arrows: items move in the page and the move is announced. Save order posts the new order.
Dragging the whole item
Use DragWholeItem to let a drag start anywhere on an item, such as cards in Columns: with a mouse after a small move, on touch after a long press, so a swipe still scrolls the page. Links, buttons and fields in an item keep their presses. With an ItemMenu there are no handles: each item's ⋯ menu ends with Move, a submenu of the moves, and Alt+arrows work on the ⋯ button. Without one, the handle stays as the menu of moves.
Preview
Code
@* DragWholeItem: each card drags from anywhere on it, with a mouse after a small move and on touch
after a long press, so a swipe still scrolls. With an ItemMenu there are no handles: each card's
⋯ menu ends with Move, a submenu of Move up, Move down, Move to top and Move to bottom. Open stands in for
a link to the tile's report: here it names the tile under the list. *@
NavigationManager Navigation
<Stack Gap="3" Grow>
<Form Model="this" FormName="list-view-tiles" OnValidSubmit="Save">
<ListView @bind-Items="_tiles" ItemKey="t => t.Id" ItemLabel="t => t.Title" Reorderable DragWholeItem Name="tiles" Order="Order"
Columns="3" Bordered Context="tile">
<ChildContent>
<Stack Gap="1">
<Heading Level="3" Size="TextSize.Md">tile.Title</Heading>
<TextBlock Size="TextSize.Sm" Color="Color.Muted">tile.Description</TextBlock>
</Stack>
</ChildContent>
<ItemMenu>
<MenuItem Href="Navigation.GetUriWithQueryParameter("tile", tile.Id)" Icon="Lucide.ExternalLink">Open</MenuItem>
</ItemMenu>
</ListView>
<FormActions><Button Submit>Save layout</Button></FormActions>
</Form>
if (Opened is not null && _tiles.FirstOrDefault(t => t.Id == Opened) is { } open)
{
<TextBlock Size="TextSize.Sm" Color="Color.Muted">Opened: open.Title.</TextBlock>
}
if (_saved is not null)
{
<TextBlock Size="TextSize.Sm" Color="Color.Muted">_saved</TextBlock>
}
</Stack>
{
[SupplyParameterFromQuery(Name = "tile")] private string? Opened { get; set; }
[SupplyParameterFromForm(FormName = "list-view-tiles", Name = "tiles")]
private ListOrder? Order { get; set; }
private IReadOnlyList<Tile> _tiles =
[
new("sales", "Sales", "Revenue this month against last."),
new("orders", "Orders", "Open, shipped and returned."),
new("traffic", "Traffic", "Visitors by source."),
new("stock", "Stock", "Items running low."),
new("support", "Support", "Tickets waiting for a reply."),
new("team", "Team", "Who's in today."),
];
private string? _saved;
private void Save()
{
// A menu move posts too; only the Save button saves.
if (Order?.Move is not null)
{
return;
}
if (Order is not null)
{
_tiles = Order.Arrange(_tiles, t => t.Id);
}
_saved = $"Saved: {string.Join(", ", _tiles.Select(t => t.Title))}.";
}
}Static: Drag a card, or press and hold one on a phone: the others move aside to show where it lands. Move in its ⋯ menu and Alt+arrows on the ⋯ button move it too. Save layout posts the new order.
Details
With no template, ItemText, ItemDescription and ItemIcon draw a row of an icon, the text and a muted second line. ItemHref makes each item a link (the whole item is clickable; links and buttons inside it still work on their own), and ItemCurrent marks the one the page is showing. OnItemClick does the same with a button, on interactive pages.
ItemActions puts content at each item's end (icon buttons, a switch, a badge), and ItemMenu gives each item a ⋯ menu of MenuItems:
<ListView Items="files" ItemKey="f => f.Id" ItemLabel="f => f.Name" Context="file">
<ChildContent>file.Name</ChildContent>
<ItemActions><IconButton Icon="Lucide.Star" Label="($"Star {file.Name}")" OnClick="() => Star(file)" /></ItemActions>
<ItemMenu><MenuItem Submit Name="delete" Value="file.Id">Delete</MenuItem></ItemMenu>
</ListView>PageSize pages the items as Table does: numbered pages or First/Previous/Next by cursor, in the URL (?page=, ?cursor=, ?size=) or, bound on an interactive page, in the component. Load more and loading on scroll add each page under the items, with the button after the last one; give the list a MaxHeight and they scroll in its box. If an ItemsProvider fails, the list shows "Couldn't load the items." with Retry.
Mode support
| Feature | Static | Interactive |
|---|---|---|
| Links, the current item, selection and paging | Yes | Yes |
| Actions on each item and its ⋯ menu (links and posting items) | Yes | Yes |
| Reordering from each handle's menu (with script off, each move posts the form) | Yes | Yes |
| Dragging, Alt+arrow shortcuts and announcements | Yes | Yes |
| The new order bound to C# | No | Yes |
Static: static server-side rendering, with no circuit and no WebAssembly. Interactive: Server, WebAssembly or Auto.
Without JavaScript
Every page starts as plain HTML: before IzzyBlazor's script loads on a static page, while an interactive page prerenders, and with JavaScript off.
- Dragging, Alt+arrow shortcuts and announcements: waits for the script
Accessibility
- It's a
uloflis withrole="list"(Safari drops a list's role without markers), so screen readers say how many items there are and where each one is. - With
ItemHreforOnItemClick, each item has one link or button, named byItemLabel(or the key), stretched over the item: one Tab stop per item. - The current item (
ItemCurrent) is markedaria-current(on its link when it has one). - A disabled item (
ItemDisabled) has no link or button, and is dimmed. - Each item's ⋯ button (
ItemMenu) is named "Actions for" and its label. Tab goes through an item's controls in order: handle, link, checkbox, content,ItemActions, the ⋯ button. - With script, arrow keys are a shortcut on top of Tab. A handle or ⋯ button keeps its arrows, which open its menu; fields keep theirs.
- With
SelectionMode, each item has a checkbox (or, for Single, a radio button) named "Select" and the item's label; with script, a "Select all rows" checkbox above a Multiple list takes the page, or every match withSelectAllMode.All. - The range under a paged list ("1–10 of 42") is read when it changes, and a failed load is announced from a status region.
Keyboard navigation
| Press this key | To do this |
|---|---|
| Tab | Go through an item's controls in order |
| Up or Down | Move to the same kind of control in the item above or below |
| Left or Right | Move to the one before or after, where items sit side by side |
| Home or End | Move to the first or last item, except from a handle or ⋯ button |
| Alt+Up or Alt+Down or Alt+Home or Alt+End | On a handle, move the item |
| Shift+Up or Shift+Down or Shift+Left or Shift+Right | On a checkbox, extend the selection |
| Ctrl+A | On an item's checkbox, select the page, or every match with SelectAllMode.All |
| Shift+F10 or Menu | Open the item's menu |
Parameters
| Prop | Type | Default |
|---|---|---|
ChildContentAn item's content. | RenderFragment<TItem>? | |
ItemTextThe default row's text. | Func<TItem, string?>? | computed |
ItemDescriptionThe default row's muted second line, such as an email address or a date. | Func<TItem, string?>? | |
ItemIconThe default row's icon, at its start. | Func<TItem, IconData?>? | |
ItemLabelNames an item for screen readers, in its link or button. | Func<TItem, string>? | computed |
ItemHrefMakes each item a link, such as to its details page. | Func<TItem, string?>? | |
ItemCurrentThe item for what the page is showing, such as the one whose details are beside the list: drawn as selected, and marked aria-current (on its link with ItemHref). | Func<TItem, bool>? | |
ItemActionsContent at the end of each item, after its text: icon buttons, a switch, a badge or a time. | RenderFragment<TItem>? | |
ItemMenuEach item's menu, of MenuItems, opened by a ⋯ button at the item's end, named "Actions for" and the item's label. | RenderFragment<TItem>? | |
ItemDisabledDims an item and leaves it without its link or button; its ItemActions and ItemMenu stay. | Func<TItem, bool>? | |
OrientationOrientation.Vertical (the default) lists the items top to bottom; Orientation.Horizontal side by side, wrapping when space runs out. | Orientation | Orientation.Vertical |
ColumnsLays the items out as cards in this many columns (2 to 6) on screens 640px and wider, such as a gallery of products. | int | 1 |
MaxHeightA height limit: the items scroll inside the list's box, with Load more after the last one. | Length? | |
CardsDraws each item as a card, with space between them rather than lines, such as the tasks in a board's columns. | bool | false |
DividersA line between items in a list. | bool | true |
BorderedA rounded border around the list. | bool | false |
SizeItem spacing and text size. | ControlSize | ControlSize.Md |
AriaLabelNames the list for screen readers, when the text around it doesn't. | string? | |
ReorderableLets the user reorder the items: each gets a handle to drag, which also opens a menu (Move up, Move down, Move to top, Move to bottom) for moving without dragging; with DragWholeItem and an ItemMenu, the moves go in each item's ⋯ menu instead, and the item drags from anywhere. | bool | false |
NameFor a Reorderable list on a static page, the prefix of the fields it posts: {Name}.Keys and {Name}.Move, bound as a ListOrder. | string? | |
OrderFor a Reorderable list on a static page, what the form posted: the list shows the posted order with the move applied, and focuses the moved item's handle (or ⋯ button). | ListOrder? | |
SubmitOnMoveFor a Reorderable list on a static page with script, posts the form after each move, for pages that save every move. | bool | false |
DragWholeItemFor a Reorderable list, lets a drag start anywhere on an item, not only on its handle: with a mouse after a small move, on touch after a long press (so a swipe still scrolls the page). | bool | false |
ZoneMakes the list a zone of the DropZoneGroup<T> around it: it shows the group's items whose zone is this one, and items move here from the group's other zones. | string? | |
AcceptsFor a Zone, which items may move here from other zones, such as t => t.Reviewed. | Func<TItem, bool>? | |
MaxItemsFor a Zone, how many items it holds at most; a full zone takes no more from the others. | int? | |
@bind-ItemsThe items. | IEnumerable<TItem>? | |
ItemsProviderLoads the items yourself, in place of Items: the request has the range (and in a Table the sort, the filter and the columns as fields), so request.ToResultAsync(query, ...) or request.Apply(query) does the work. | Func<DataRequest<TItem>, ValueTask<DataResult<TItem>>>? | |
@bind-PageSizeItems per page. | int? | |
PageSizeOptionsSizes to choose from in a "Rows per page" menu in the footer, such as new[] { 10, 25, 50 }. | IReadOnlyList<int>? | |
@bind-PageThe page, from 1. | int? | |
PagingHow it moves through its pages when it has a PageSize: numbered pages (DataPaging.Pages, the default, which needs a total), or by cursor, with no total needed: First, Previous and Next (DataPaging.NextPrevious), a "Load more" button after the items (DataPaging.LoadMore, ListView only), or loading as the last item comes into view (DataPaging.LoadOnScroll). | DataPaging | DataPaging.Pages |
LoadMoreTextThe "Load more" button's text, such as "Load earlier". | string? | "Load more" |
@bind-CursorThe cursor of the page shown when paging by cursor (Paging); null for the first page. | string? | |
QueryPrefixPrefix for its query-string keys, so several can share a page: QueryPrefix="orders-" uses ?orders-page= (and a Table's ?orders-sort=). | string | "" |
EmptyContentShown when there are no items. | RenderFragment? | computed |
EmptyTextThe text when there are no items. | string? | "No items" |
ErrorContentShown in place of "Couldn't load the rows." when loading fails, before the Retry button. | RenderFragment? | |
ItemKeyA unique, stable key for each item, such as its id. | Func<TItem, string>? | computed |
LoadingShows it as loading: items dim, or placeholders show while there are none. | bool | false |
SelectionModeWhether items can be selected: one (a radio button on each) or several (a checkbox on each). | SelectionMode | SelectionMode.None |
SelectionNameThe form field name the selection posts under, read back as a Selection with [SupplyParameterFromForm(Name = ...)]. | string? | computed |
@bind-SelectionThe selected items: keys on any page, or every item matching the filter except some. | Selection? | |
ItemSelectableWhether an item can be selected; others show a disabled, unchecked box, and selecting the page or a range leaves them out. | Func<TItem, bool>? | |
SelectAllModeWhat the select-all checkbox selects: the items on this page, or every item the filters match, on any page. | SelectAllMode | SelectAllMode.Page |
SelectionActionsActions on the selection, in a bar above the items, disabled until something is selected (on a DataGrid with a toolbar, the bar takes the toolbar's place while something is). | RenderFragment<Selection>? | |
SelectAllLabelThe select-all checkbox's name for screen readers. | string? | "Select all rows" |
SelectRowLabelThe start of each item checkbox's name for screen readers, before the item's label. | string? | "Select" |
OnItemClickMakes each item a button that runs this, on interactive pages. | EventCallback<TItem> | |
OnMoveRuns before a move changes the list, on interactive pages: save it here, or set Cancel to keep the item where it was. | EventCallback<ListMoveEventArgs<TItem>> |
Plus 16 item props and 4 common props.
Full API