Skip to main content

DxListBox<TData, TValue> Class

A component that can connect to a data source and display a list of selectable items.

Namespace: DevExpress.Blazor

Assembly: DevExpress.Blazor.v24.2.dll

NuGet Package: DevExpress.Blazor

Declaration

public class DxListBox<TData, TValue> :
    DxListEditorBase<TData, TValue>,
    IListBoxComponent<TData, TValue>,
    IListBox<TData, TValue>,
    IListEditorBase<TData, TValue>,
    IEditorBase,
    IListBoxAccessor<TData>,
    IListEditorAccessorBase<TData>

Type Parameters

Name Description
TData

The data item type.

TValue

The value type.

Remarks

The DevExpress List Box for Blazor (<DxListBox>) allows you to display a list of selectable items from a data source.

List Box

Run Demo: List Box - Overview

Add a List Box to a Project

Follow the steps below to add a List Box component to an application:

  1. Use a DevExpress Project Template to create a new Blazor Server or Blazor WebAssembly application. If you use a Microsoft project template or already have a Blazor project, configure your project to incorporate DevExpress Blazor components.
  2. Add the <DxListBox></DxListBox> markup to a .razor file.
  3. Bind the component to data.
  4. Configure the component: handle an item selection, customize item appearance, and so on (see sections below).

.NET 8 and .NET 9 Specifics

Blazor ListBox does not support static render mode. Enable interactivity to use the component in your application. Refer to the following topic for more details: Enable Interactive Render Mode.

Bind to Data

Strongly Typed Collection

Use the Data property to bind the List Box to a strongly typed collection. Initialize this collection in the OnInitialized lifecycle method or before this method is invoked. Use the DataAsync property instead of the Data property if a strongly typed collection is loaded asynchronously (for instance, from an HTTP request).

Use the Value or Values property to select one or multiple List Box items programmatically. You can use the @bind attribute to bind these properties to a data field. Refer to the following topic for more information: Two-Way Data Binding.

<DxListBox Data="@Cities" @bind-Values="@Values"></DxListBox>

@code {
  IEnumerable<string> Cities = new List<string>() {
    "London",
    "Berlin",
    "Paris",
  };

  IEnumerable<string> Values { get; set; } 
}

The List Box control can detect IQueryable collections and use benefits of the corresponding LINQ query providers (such as Entity Framework).

Custom Object Collection

You can bind the List Box to a data collection (Data) that stores custom objects (IEnumerable<CustomType>). The Values collection can also contain custom objects. In this case, you need to override the following methods for your custom object:

  • GetHashCode(). The List Box uses hash codes to compare items. Override this method to make sure that compared objects have the same hash code.

  • Equals. The default Equals method determines whether two object instances are equal. The compared items will not be equal if they are different instances (even if they have exactly the same properties). As a result, the component will not display the selected items.

You also need to set the List Box’s TextFieldName property. It specifies the custom object’s field name that returns strings to be shown in the List Box. If the TextFieldName property is not specified, the List Box component searches for a Text field in the data source and uses this field as a text field. Otherwise, the List Box is populated with CustomType.ToString() values.

As an alternative, you can use KeyFieldName and KeyFieldNames properties to specify which field the List Box should use as an identifier to compare items.

@using StaffData

<DxListBox Data="@Staff.DataSource"
           @bind-Values="@Values"
           TextFieldName="@nameof(Person.Text)">
</DxListBox>

@code {
    IEnumerable<Person> Values { get; set; } = Staff.DataSource.Take(1);
}

List Box

Run Demo: List Box - Overview

Custom Data

When you bind an editor to data from a Web API service, assign the data type to the component’s T parameter and use the CustomData property to implement custom data load logic.

View Example: Data Editors for Blazor - Custom data binding

You can also enable Virtual Scrolling to improve client-side performance.

Item Selection

Use the SelectionMode property to change the selection mode. The component supports the following modes:

Single (default)

Users can only select one List Box item at a time. A user should click a List Box item to select it.

Use the Value property to access/specify the selected item in code. To respond to selection changes, handle the ValueChanged event.

Multiple

Users can select multiple items in the List Box. A user should click the initial item, hold the Shift key, and select the final item to specify the range of items. To add/remove individual items to/from the selection, a user should click an item with the Ctrl key pressed. Enable the ShowCheckboxes property to allow users to use checkboxes to select items.

Use the Values property to access/specify selected items in multiple selection mode. To respond to selection changes, handle the ValuesChanged event.

None (selection functionality is disabled)
Users cannot select List Box items.

The following code snippet enables multiple selection in the List Box and adds checkboxes to the component. Users can click items or corresponding checkboxes to change selection.

@using StaffData

<DxListBox Data="@Staff.DataSource"
           TextFieldName="@nameof(Person.Text)"
           SelectionMode="ListBoxSelectionMode.Multiple"
           ShowCheckboxes="true"
           @bind-Values="@Values">
</DxListBox>

@code {
    IEnumerable<Person> Values { get; set; }
}

ListBox ShowCheckboxes

Run Demo: List Box - Multiple Selection

Multiple Columns

The List Box control can display data across multiple columns. Follow the steps below to create columns:

  1. Add a <Columns> tag to the component’s markup to declare the column collection.
  2. Populate the Columns collection with DxListEditorColumn objects. These objects include the following properties:

    • Caption - Specifies the column’s caption text.
    • FieldName - Specifies the data source field that populates column items in multi-column editors.
    • SearchEnabled - Specifies whether the component can search text in cells of the current column.
    • Visible - Specifies whether the column is visible.
    • VisibleChanged - Fires when the column visibility changes.
    • VisibleIndex - Specifies a column’s position among other columns.
    • VisibleIndexChanged - Fires when the column’s visible index changes.
    • Width - Specifies the column’s width.
@using StaffData

<DxListBox Data="@Staff.DataSource"
           @bind-Values="@Values">
    <Columns>
        <DxListEditorColumn FieldName="Id" Width="50px" />
        <DxListEditorColumn FieldName="FirstName" Caption="Name"/>
        <DxListEditorColumn FieldName="LastName" Caption="Surname"/>
    </Columns>
</DxListBox>

@code {
    IEnumerable<Person> Values { get; set; } = Staff.DataSource.Take(1);
}

List Box - Multiple Columns

Run Demo: List Box – Multiple Columns

Group Data

The Blazor ListBox allows you to organize list items into groups. This enhance user experience by allowing users to locate required values faster. To group data, specify the GroupFieldName property. Values from the specified field appear within group headers.

Note the following specifics:

  • The ListBox supports only one group level.
  • Users cannot collapse groups.
  • Group headers do not take part in search operations.
  • Multi-column ListBox controls also support groups.
  • You can use the GroupHeaderDisplayTemplate property to customize group headers.

The following code organizes data items into groups based on the Country data source field:

@inject NwindDataService NwindDataService

<DxListBox Data="@Data"
           @bind-Value="@Value"
           ShowSearchBox="true"
           @bind-SearchText="@SearchText"
           TextFieldName="@nameof(Customer.ContactName)"
           GroupFieldName="@nameof(Customer.Country)">
</DxListBox>

@code {
    string SearchText { get; set; }
    IEnumerable<Customer> Data { get; set; }
    Customer Value { get; set; }
    protected override async Task OnInitializedAsync() {
        Data = await NwindDataService.GetCustomersAsync();
        Value = Data.FirstOrDefault(x => x.Country == "Argentina");
    }
}

List Box - Group Data

Run Demo: List Box – Group Data

Virtual Scrolling

Set the ListRenderMode property to ListRenderMode.Virtual to enable virtual scrolling. In this mode, the List Box renders data on demand when a user scrolls list items.

@using StaffData

<DxListBox Data="@Staff.DataSource"
           TData="Person"
           TValue="Person"
           ListRenderMode="ListRenderMode.Virtual">
</DxListBox>

Run Demo: List Box - Virtual Scrolling

Item Display Template

The ItemDisplayTemplate property allows you to customize the appearance of List Box items. The property accepts a ListBoxItemDisplayTemplateContext<TData> object as the context parameter. You can use the parameter’s members to get information about items:

The following code snippet displays List Box items as contact cards. Each item shows an employee’s first name, last name, photo, and phone number.

@inject NwindDataService NwindDataService

<DxListBox Data="@Data"
            @bind-Value="@Value"
            SizeMode="Params.SizeMode"
            CssClass="cw-400 chi-220">
    <ItemDisplayTemplate>
        <div class="listbox-item-template">
            <img src="@StaticAssetUtils.GetImagePath(GetImageFileName(context.DataItem))" alt="@context.DataItem.FullName" />
            <div class="listbox-item-template-text">
                <span>@context.DataItem.FullName</span>
                <span class="listbox-item-template-text-phone">@context.DataItem.HomePhone</span>
            </div>
        </div>
    </ItemDisplayTemplate>
</DxListBox>

@code {
    IEnumerable<Employee> Data { get; set; }
    Employee Value { get; set; }

    protected override async Task OnInitializedAsync() {
        Data = await NwindDataService.GetEmployeesAsync();
        Value = Data.FirstOrDefault();
    }

    string GetImageFileName(Employee employee) {
        return $"employees/item-template{employee.EmployeeId}.jpg";
    }
}

ListBox - Item Display Template

Run Demo: ListBox - Item Display Template

Column Cell Display Template

The ColumnCellDisplayTemplate allows you to specify custom content and change cell appearance in List Box columns. The template accepts a ListBoxColumnCellDisplayTemplateContext<TData> object as the context parameter. You can use the parameter’s members to get information about columns.

The following code snippet customizes the appearance of different columns.

@inject NwindDataService NwindDataService

<DxListBox TData="Product" TValue="Product" Data="@Data"
            @bind-Values="@SelectedProducts"
            SelectionMode="ListBoxSelectionMode.Multiple">
    <Columns>
        <DxListEditorColumn FieldName="@nameof(Product.ProductName)" Caption="Product" Width="30%"/>
        <DxListEditorColumn FieldName="@nameof(Product.UnitPrice)" Caption="Unit Price"/>
        <DxListEditorColumn FieldName="@nameof(Product.Quantity)"/>
        <DxListEditorColumn FieldName="@nameof(Product.Discount)"/>
        <DxListEditorColumn FieldName="@nameof(Product.Total)" />
    </Columns>
    <ColumnCellDisplayTemplate>
        @{
            object displayValue;
            string cssClass = string.Empty;
            switch (context.Column.FieldName) {
                case nameof(Product.UnitPrice):
                    cssClass = alignRightCssClass;
                    displayValue = $"{context.Value:c}";
                    break;
                case nameof(Product.Quantity):
                    cssClass = alignRightCssClass;
                    displayValue = context.DisplayText;
                    break;
                case nameof(Product.Discount):
                    displayValue = $"{context.Value:p}";
                    break;
                case nameof(Product.Total):
                    var value = context.DataItem.UnitPrice * context.DataItem.Quantity;
                    var valueCssClass = value >= totalPriceCeiling ? textGreenCssClass : textRedCssClass;
                    cssClass = $"{alignRightCssClass} {valueCssClass}";
                    displayValue = $"{value:c}";
                    break;
                default:
                    displayValue = context.DisplayText;
                    break;
            }
        }
        <div class="@cssClass">@displayValue</div>
    </ColumnCellDisplayTemplate>
</DxListBox>

@code {
    IEnumerable<Product> Data { get; set; }
    IEnumerable<Product> SelectedProducts { get; set; }
    int totalPriceCeiling = 100;
    string alignRightCssClass = "align-right";
    string textGreenCssClass = "text-green";
    string textRedCssClass = "text-red";
    protected override async Task OnInitializedAsync() {
        var invoices = await NwindDataService.GetInvoicesAsync();
        var products = await NwindDataService.GetProductsAsync();
        Data = invoices.Join(products, i => i.ProductId, p => p.ProductId, (i, p) =>
            new Product {
                ProductName = i.ProductName,
                UnitPrice = i.UnitPrice,
                Quantity = i.Quantity,
                Discount = i.Discount
            }
        );
        SelectedProducts = Data.Skip(1).Take(3);
    }
    public class Product {
        public string ProductName { get; set; }
        public decimal UnitPrice { get; set; }
        public int Quantity { get; set; }
        public float Discount { get; set; }
        public int Total { get; set; }
        public override bool Equals(object obj) {
            return obj is Product product && string.Equals(product.ProductName, ProductName) && product.Quantity == Quantity;
        }
        public override int GetHashCode() {
            return HashCode.Combine(ProductName, Quantity);
        }
    }
}

ListBox - Column Cell Display Template

Run Demo: List Box - Column Cell Display Template

Empty Data Area Template

The List Box displays an empty data area in the following cases:

  • The Data property is unset.
  • The specified data source does not contain items.
  • You use the DataAsync property or the CustomData property to bind the List Box to a data source. The component sends the first request to a remote data source and waits for a response.

Use the EmptyDataAreaTemplate to customize content displayed in the empty data area. The template’s context parameter has the IsDataLoading property that allows you to determine whether the List Box data is still loading data.

The following code snippet embeds the Wait Indicator component into the List Box.

@inject NwindDataService NwindDataService
<DxListBox TData="@WebApiLookup" TValue="string"
           ListRenderMode="ListRenderMode.Virtual"
           CssClass="cw-400 chi-220"
           CustomData="@LoadCustomData"
           @key="ComponentKey">
    <EmptyDataAreaTemplate>
        @if (context.IsDataLoading) {
            <div class="empty-data-area-template">
                <div class="d-flex flex-column">
                    <DxWaitIndicator Visible="true"
                                     CssClass="m-auto"
                                     AnimationType="WaitIndicatorAnimationType.Spin" />
                    <p class="dxbl-text d-block mt-1">Loading, please wait...</p>
                </div>
            </div>
        }
    </EmptyDataAreaTemplate>
</DxListBox>

@code {
    [Inject] protected HttpClient Client { get; set; }
    Guid ComponentKey { get; set; } = Guid.NewGuid();
    async Task<LoadResult> LoadCustomData(DataSourceLoadOptionsBase options, CancellationToken cancellationToken) {
        using var response = await Client.GetAsync(options.ConvertToGetRequestUri
            ("https://js.devexpress.com/Demos/NetCore/api/DataGridWebApi/CustomersLookup"), cancellationToken);
        response.EnsureSuccessStatusCode();
        if(options.RequireTotalCount)
            await Task.Delay(3000, cancellationToken);
        using var responseStream = await response.Content.ReadAsStreamAsync();
        var result = await JsonSerializer.DeserializeAsync<LoadResult>(responseStream, cancellationToken: cancellationToken);
        return result;
    }
    void ReloadListBox() {
        ComponentKey = Guid.NewGuid();
    }
    public class WebApiLookup {
        public string Text { get; set; }
        public string Value { get; set; }
    }
}

ListBox - Empty Data Area Template

Run Demo: List Box - Empty Data Area Template

Search and Filter Data

The Blazor List Box ships with API members that allow you to use search and filter capabilities.

Use the ShowSearchBox property to display the search box in the List Box component. Once a user enters the text in the search box, the List Box looks for rows with matching values, highlights search results, and filters out all other rows. Search is case-insensitive and applies to cells in visible columns only.

<DxListBox TData=Person TValue=Person Data="Staff.DataSource"
            ShowSearchBox="true"           
            ShowCheckboxes="true"
            SelectionMode="@ListBoxSelectionMode.Multiple">
    <Columns>
        <DxListEditorColumn FieldName="FirstName"></DxListEditorColumn>
        <DxListEditorColumn FieldName="LastName"></DxListEditorColumn>
        <DxListEditorColumn FieldName="Department"></DxListEditorColumn>
    </Columns>
</DxListBox>

@code {
    public string SearchText { get; set; }
}

Search Box Overview

Run Demo: List Box - Search Box

Search Text

You can use the SearchText property to specify the search text in code. Refer to Search Syntax.

<DxListBox TData=Person TValue=Person Data="Staff.DataSource"
            ShowCheckboxes="true"
            SearchText="Sa"
            SelectionMode="@ListBoxSelectionMode.Multiple">
    <Columns>
        <DxListEditorColumn FieldName="FirstName"></DxListEditorColumn>
        <DxListEditorColumn FieldName="LastName"></DxListEditorColumn>
        <DxListEditorColumn FieldName="Department"></DxListEditorColumn>
    </Columns>
</DxListBox>

Search Text

To respond to search text changes, handle the SearchTextChanged event. The event is handled automatically when you use two-way data binding for the SearchText property (@bind-SearchText).

Set a column’s SearchEnabled property to false to exclude a specific column from search operations.

If the search text contains multiple words separated by space characters, the words can be treated as a single condition or individual conditions based on the SearchTextParseMode property value.

Filter Criteria

The List Box allows you to filter its data in code. You can create a criteria operator object that specifies the filter expression and pass this object to the SetFilterCriteria(CriteriaOperator) method. To get the applied filter criteria, use the GetFilterCriteria() method.

For more information about criteria operators, see the following topics:

When a filter is applied, the List Box raises the FilterCriteriaChanged event.

You can call the ClearFilter() method to clear any previously applied filters and apply a new filter to list box data.

The following code creates a toolbar that allows you to apply filter criteria to List Box data and clear filter.

<DxToolbar ItemClick="@OnItemClick">
    <Items>
        <DxToolbarItem Name="_setFilterCriteria" Text="Set Filter Criteria" Tooltip="Set Filter Criteria" />
        <DxToolbarItem Name="_clearFilterCriteria" Text="Clear Filter Criteria" Tooltip="Clear Filter Criteria" />
    </Items>
</DxToolbar>
<br/>
<DxListBox @ref="@_listBox" TData=Person TValue=Person Data="Staff.DataSource"
            ShowCheckboxes="true"
            SelectionMode="@ListBoxSelectionMode.Multiple">
    <Columns>
        <DxListEditorColumn FieldName="FirstName"></DxListEditorColumn>
        <DxListEditorColumn FieldName="LastName"></DxListEditorColumn>
        <DxListEditorColumn FieldName="Department"></DxListEditorColumn>
        <DxListEditorColumn FieldName="Salary"></DxListEditorColumn>
    </Columns>
</DxListBox>
<p class="cw-480 mt-3">
    Filter Criteria: <b>@_listBox?.GetFilterCriteria()?.ToString()</b>
</p>

@code {
    IListBox<Person, Person> _listBox;
    void OnItemClick(ToolbarItemClickEventArgs e) {
        switch(e.ItemName) {
            case "_setFilterCriteria":
                _listBox.SetFilterCriteria(new BinaryOperator(nameof(Person.Salary), 2000, BinaryOperatorType.Greater));
                break;
            case "_clearFilterCriteria":
                _listBox.ClearFilter();
                break;
        }
    }
}

Filter Criteria

Run Demo: List Box - Filter Criteria

Disabled Items

You can disable individual items in the List Box. To do this, use the DisabledFieldName property. The property specifies a Boolean field that stores each item’s enabled or disabled state. Disabled items are grayed out and cannot be selected.

Note

Disabled items can improve component usability, but cannot replace adequate security measures. Users may still be able to select disabled items on the client side, so you should implement appropriate security checks in your code.

@inject NwindDataService NwindDataService

<DxListBox Data="@Products"
           @bind-Values="@SelectedProducts"
           TextFieldName="@nameof(Product.ProductName)"
           DisabledFieldName="@nameof(Product.Discontinued)"
           SelectionMode="ListBoxSelectionMode.Multiple"
           CssClass="cw-400 chi-220">
</DxListBox>

@code {
    IEnumerable<Product> Products { get; set; }
    IEnumerable<Product> SelectedProducts { get; set; }
    protected override async Task OnInitializedAsync() {
        Products = await NwindDataService.GetProductsAsync();
        SelectedProducts = Products.Take(1);
    }
}

List Box - Disabled Items

Run Demo: List Box – Disabled Items

Input Validation

You can add a standalone List Box or the corresponding Form Layout component to the Blazor’s standard EditForm. This form validates user input based on data annotation attributes defined in a model and indicates errors.

<EditForm Model="@model" Context="EditFormContext">
    <DataAnnotationsValidator />
    <DxFormLayout >
        <DxFormLayoutItem Caption="Values:" ColSpanMd="6" >
            <DxListBox Data="@(new List<string>() { "Defense", "Exploration", "Diplomacy" })"
                       @bind-Values="@model.Values" />
        </DxFormLayoutItem >
        @*...*@
    </DxFormLayout>
</EditForm>

@code {
    private Model model=new Model();
}

If you handle the ValueChanged event and cannot use two-way binding, specify the ValueExpression or ValuesExpression property to identify the value passed to the event handler.

For more information, refer to the following help topic: Validate Input.

Run Demo: Form Validation

Keyboard Navigation

The DevExpress Blazor List Box supports keyboard navigation. Users can navigate through List Box items and select them.

Run Demo: List Box

When a user focuses the List Box component, the first selected item or first selected row (in multiple columns mode) is focused.

The following shortcut keys are available:

Shortcut Keys Description
Tab, Shift + Tab When the List Box is focused, moves focus to the next/previous focusable element on a page.
Up Arrow Moves focus one item up.
Down Arrow Moves focus one item down.
Home Moves focus to the first item or the first row (in multiple columns mode).
End Moves focus to the last item or the last row (in multiple columns mode).
Page Up Moves focus to the previous item page.
Page Down Moves focus to the next item page.
Enter If the focused item contains an ItemDisplayTemplate or a ColumnCellDisplayTemplate, moves focus to the first element in the template. Users can use Tab to navigate through inner elements (buttons, links, etc.).
Space Selects the focused item/row, deselects previously selected items/rows. Updates Value and Values parameter values.
Shift + Space In multiple selection mode, selects a range of items between the previously selected item and the focused item.
Ctrl + Shift + Home In multiple selection mode, selects the focused item and all items above it, focuses the first item.
Ctrl + Shift + End In multiple selection mode, selects the focused item and all items below it, focuses the last item.

Note

In read-only state, List Box supports keyboard navigation, but users cannot select items.

When the Enabled property is set to false, the editor does not respond to user interactions.

Read-Only State

<DxListBox> supports read-only state. Set the ReadOnly‘ property to true to activate this option.

@using StaffData

<DxListBox Data="@Staff.DataSource"
           Values="@Values"
           ReadOnly="true" />

@code {
    IEnumerable<Person> Values => Staff.DataSource.Take(1);
}

Run Demo: List Box - Read-Only and Disabled Modes

Troubleshooting

If a Blazor application throws unexpected exceptions, refer to the following help topic: Troubleshooting.

Inheritance

Object
ComponentBase
DxComponentBase
DevExpress.Blazor.Internal.ParameterTrackerComponent
DxEditorBase
DxListEditorBase<TData, TValue>
DxListBox<TData, TValue>
See Also