Skip to content
IzzyBlazor 0.1.0-alpha.20

Enter all results ↑ ↓ move Esc close

ListView

Since 0.1.0-alpha.20
Items from data, each drawn by a template; links, selection, reordering and paging.

Static 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

razor
<ListView Items="people" ItemKey="p => p.Id" ItemHref="@(p => $"/people/{p.Id}")" Context="person">
    <Avatar Name="@person.Name" /> @person.Name
</ListView>

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

Code

Contacts.razor
@* 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=".) *@
@inject 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" />

@code {
    [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

  • Quarterly report draftGrace Hopper
  • Lunch on Friday?Alan Turing
  • Build failed on mainCI
  • Invoice #1042Billing

Code

SelectItems.razor
@* 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>

@code {
    // 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

  • Quarterly report.pdf2.4 MB, edited today
  • Brand guidelines.pdf8.1 MB, shared by Grace
    Shared
  • Budget 2027.xlsx640 KB, edited Monday

Code

Actions.razor
@* 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>

@code {
    // 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

    New

    Oak 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

    New

    Cushioned, with beveled edges.

    $59.00

  • Wall shelf

    Wall shelf

    Floating, holds 20 kg.

    $89.00

Code

Cards.razor
@* 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. *@
@inject 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>

@code {
    [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
1–4 of 11

Code

LoadMore.razor
@* 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 />

@code {
    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
1–8 of 40

Code

LoadOnScroll.razor
@* 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 />

@code {
    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

  • Draft
  • Review
  • Approve
  • Publish

Code

SaveOrder.razor
@* 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>

@code {
    [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

  • Sales

    Revenue this month against last.

    Open
  • Orders

    Open, shipped and returned.

    Open
  • Traffic

    Visitors by source.

    Open
  • Stock

    Items running low.

    Open
  • Support

    Tickets waiting for a reply.

    Open
  • Team

    Who's in today.

    Open

Code

DragCards.razor
@* 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. *@
@inject 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>

@code {
    [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:

razor
<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

What works in each mode, ListView
FeatureStaticInteractive
Links, the current item, selection and pagingYesYes
Actions on each item and its ⋯ menu (links and posting items)YesYes
Reordering from each handle's menu (with script off, each move posts the form)YesYes
Dragging, Alt+arrow shortcuts and announcementsYesYes
The new order bound to C#NoYes

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 ul of lis with role="list" (Safari drops a list's role without markers), so screen readers say how many items there are and where each one is.
  • With ItemHref or OnItemClick, each item has one link or button, named by ItemLabel (or the key), stretched over the item: one Tab stop per item.
  • The current item (ItemCurrent) is marked aria-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 with SelectAllMode.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

ListView keys
Press this keyTo do this
TabGo through an item's controls in order
Up or DownMove to the same kind of control in the item above or below
Left or RightMove to the one before or after, where items sit side by side
Home or EndMove to the first or last item, except from a handle or ⋯ button
Alt+Up or Alt+Down or Alt+Home or Alt+EndOn a handle, move the item
Shift+Up or Shift+Down or Shift+Left or Shift+RightOn a checkbox, extend the selection
Ctrl+AOn an item's checkbox, select the page, or every match with SelectAllMode.All
Shift+F10 or MenuOpen the item's menu

Parameters

ListView parameters
PropTypeDefault
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.OrientationOrientation.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.int1
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.boolfalse
DividersA line between items in a list.booltrue
BorderedA rounded border around the list.boolfalse
SizeItem spacing and text size.ControlSizeControlSize.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.boolfalse
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.boolfalse
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).boolfalse
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).DataPagingDataPaging.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.boolfalse
SelectionModeWhether items can be selected: one (a radio button on each) or several (a checkbox on each).SelectionModeSelectionMode.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.SelectAllModeSelectAllMode.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>>

See also

  • Table: sort, filter, page and select, with state in the URL.
  • List: bulleted, numbered, plain or icon lists.

Connection lost

Rejoining the server…