List Box
An always-visible list of options. No trigger, no popover: the choices stay on screen, which is what a settings panel, a transfer list or a filter pane wants. It carries the whole ARIA listbox pattern — one tab stop, a roving active option, range selection and typeahead.
List Box, Select or Multi Select?
They are the same list. Use List Box when the choices should stay on screen, and
Select or
Multi Select when they should stay out of the way until asked for.
All three take the same
SelectOption<TValue>, so options move between them unchanged.
Single Selection
The default. One option at a time, bound with
@bind-Value. Moving with the arrow keys selects as it goes, which is how a native list behaves. Click into the list and try ↑ ↓, Home, End, or just type the first letter of an option.Multiple Selection, Search and Select All
SelectionMode="ListBoxSelectionMode.Multiple" binds through @bind-Values instead. The arrow keys now move without selecting; Space toggles, Shift with an arrow or a click extends a range, and Ctrl+A takes everything. Select-all covers what the search has left visible, not the hidden rest — a control that quietly selected rows you could not see would be worse than no shortcut at all.Unavailable Rows and a Custom Row
OptionDisabled takes the whole option rather than a value, so the rule can read either. A disabled row is skipped by the arrow keys, by select-all and by Ctrl+A rather than stopping them dead. ItemTemplate replaces an option's content; the selection indicator is drawn either way, because a focusable checkbox inside every option would be a second tab stop and a second thing to announce when aria-selected already carries the state.Reading What the Search Left Visible
SearchText is bindable but not required — typing in the search box works whether or not a parent binds it. Bind it when the parent has to know which options are on screen rather than guess. This is exactly what Pick List uses to move only what a search has left visible.Empty and Disabled States
EmptyMessage defaults to the localized “No matches” while a search is typed and “No options” otherwise. Disabled draws the root at reduced opacity and removes the list from the tab order entirely, so it cannot be reached by keyboard.Inside an EditForm
Both bindings carry an expression —
ValueExpression and ValuesExpression — which Blazor supplies automatically from @bind-Value or @bind-Values. The cascaded EditContext is picked up on its own, so validation works with nothing else wired up.