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");
}
}
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace BlazorDemo.Data.Northwind {
public partial class Customer {
public Customer() {
Orders = new HashSet<Order>();
}
public string CustomerId { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
public string ContactTitle { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Region { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}
}
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BlazorDemo.Data.Northwind;
using BlazorDemo.DataProviders;
namespace BlazorDemo.Services {
public partial class NwindDataService {
public Task<IEnumerable<Customer>> GetCustomersAsync(CancellationToken ct = default) {
// Return your data here
}
}
}
using BlazorDemo.Services;
using Microsoft.Extensions.DependencyInjection;
public class Startup {
public void ConfigureServices(IServiceCollection services) {
// ...
services.AddScoped<NwindDataService>();
}
}

Run Demo: List Box – Group Data
Search and Filter Data
The Blazor List Box ships with API members that allow you to use search and filter capabilities.
Search Box
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; }
}
namespace StaffData {
public static class Staff {
private static readonly Lazy<List<Person>> dataSource = new Lazy<List<Person>>(() => {
var dataSource = new List<Person>() {
new Person() { Id= 0 , FirstName="John", LastName="Heart", Department=Department.Electronics },
new Person() { Id= 1 , FirstName="Samantha", LastName="Bright", Department=Department.Motors },
new Person() { Id= 2 , FirstName="Arthur", LastName="Miller", Department=Department.Software },
new Person() { Id= 3 , FirstName="Robert", LastName="Reagan", Department=Department.Electronics },
new Person() { Id= 4 , FirstName="Greta", LastName="Sims", Department=Department.Motors },
new Person() { Id= 5 , FirstName="Brett", LastName="Wade", Department=Department.Software },
new Person() { Id= 6 , FirstName="Sandra", LastName="Johnson", Department=Department.Electronics },
new Person() { Id= 7 , FirstName="Edward", LastName="Holmes", Department=Department.Motors },
new Person() { Id= 8 , FirstName="Barbara", LastName="Banks", Department=Department.Software },
new Person() { Id= 9 , FirstName="Kevin", LastName="Carter", Department=Department.Electronics },
new Person() { Id= 10, FirstName="Cynthia", LastName="Stanwick", Department=Department.Motors },
new Person() { Id= 11, FirstName="Sam", LastName="Hill", Department=Department.Electronics }};
return dataSource;
});
public static List<Person> DataSource { get { return dataSource.Value; } }
}
public class Person {
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Department Department { get; set; }
public string Text => $"{FirstName} {LastName} ({Department} Dept.)";
public override bool Equals(object obj) {
if (obj is Person typedObj) {
return (this.Id == typedObj.Id) && (this.FirstName == typedObj.FirstName) && (this.LastName == typedObj.LastName)
&& (this.Department == typedObj.Department);
}
return base.Equals(obj);
}
}
public enum Department { Motors, Electronics, Software }
}

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>
namespace StaffData {
public static class Staff {
private static readonly Lazy<List<Person>> dataSource = new Lazy<List<Person>>(() => {
var dataSource = new List<Person>() {
new Person() { Id= 0 , FirstName="John", LastName="Heart", Department=Department.Electronics },
new Person() { Id= 1 , FirstName="Samantha", LastName="Bright", Department=Department.Motors },
new Person() { Id= 2 , FirstName="Arthur", LastName="Miller", Department=Department.Software },
new Person() { Id= 3 , FirstName="Robert", LastName="Reagan", Department=Department.Electronics },
new Person() { Id= 4 , FirstName="Greta", LastName="Sims", Department=Department.Motors },
new Person() { Id= 5 , FirstName="Brett", LastName="Wade", Department=Department.Software },
new Person() { Id= 6 , FirstName="Sandra", LastName="Johnson", Department=Department.Electronics },
new Person() { Id= 7 , FirstName="Edward", LastName="Holmes", Department=Department.Motors },
new Person() { Id= 8 , FirstName="Barbara", LastName="Banks", Department=Department.Software },
new Person() { Id= 9 , FirstName="Kevin", LastName="Carter", Department=Department.Electronics },
new Person() { Id= 10, FirstName="Cynthia", LastName="Stanwick", Department=Department.Motors },
new Person() { Id= 11, FirstName="Sam", LastName="Hill", Department=Department.Electronics }};
return dataSource;
});
public static List<Person> DataSource { get { return dataSource.Value; } }
}
public class Person {
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Department Department { get; set; }
public string Text => $"{FirstName} {LastName} ({Department} Dept.)";
public override bool Equals(object obj) {
if (obj is Person typedObj) {
return (this.Id == typedObj.Id) && (this.FirstName == typedObj.FirstName) && (this.LastName == typedObj.LastName)
&& (this.Department == typedObj.Department);
}
return base.Equals(obj);
}
}
public enum Department { Motors, Electronics, Software }
}

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.
@using DevExpress.Data.Filtering
<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;
}
}
}
namespace StaffData {
public static class Staff {
private static readonly Lazy<List<Person>> dataSource = new Lazy<List<Person>>(() =>
{
Random rnd = new Random();
var dataSource = new List<Person>() {
new Person() { Id = 0 , FirstName = "John John", LastName = "Heart", Department = Department.Electronics, Salary = GetRandomSalary(rnd) },
new Person() { Id = 1 , FirstName = "Samantha", LastName = "Bright", Department = Department.Motors, Salary = GetRandomSalary(rnd) },
new Person() { Id = 2 , FirstName = "Arthur", LastName = "Miller", Department = Department.Software, Salary = GetRandomSalary(rnd) },
new Person() { Id = 3 , FirstName = "Robert", LastName = "Reagan", Department = Department.Electronics, Salary = GetRandomSalary(rnd) },
new Person() { Id = 4 , FirstName = "Greta", LastName = "Sims", Department = Department.Motors, Salary = GetRandomSalary(rnd) },
new Person() { Id = 5 , FirstName = "Brett", LastName = "Wade", Department = Department.Software, Salary = GetRandomSalary(rnd) },
new Person() { Id = 6 , FirstName = "Sandra", LastName = "Johnson", Department = Department.Electronics, Salary = GetRandomSalary(rnd) },
new Person() { Id = 7 , FirstName = "Edward", LastName = "+Holmes", Department = Department.Motors, Salary = GetRandomSalary(rnd) },
new Person() { Id = 8 , FirstName = "Barbara", LastName = "Banks", Department = Department.Software, Salary = GetRandomSalary(rnd) },
new Person() { Id = 9 , FirstName = "Kevin", LastName = "Carter", Department = Department.Electronics, Salary = GetRandomSalary(rnd) },
new Person() { Id = 10, FirstName = "Cynthia", LastName = "Stanwick", Department = Department.Motors, Salary = GetRandomSalary(rnd) },
new Person() { Id = 11, FirstName = "Sam", LastName = "Hill", Department = Department.Electronics, Salary = GetRandomSalary(rnd) },
};
return dataSource;
});
public static List<Person> DataSource { get { return dataSource.Value; } }
}
public class Person {
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Department Department { get; set; }
public string Text => $"{FirstName} {LastName} ({Department} Dept.)";
public decimal Salary { get; set; }
public DateTime BirthDate { get; set; }
public override bool Equals(object obj) {
if (obj is Person typedObj) {
return (this.Id == typedObj.Id) && (this.FirstName == typedObj.FirstName) && (this.LastName == typedObj.LastName)
&& (this.Department == typedObj.Department);
}
return base.Equals(obj);
}
}
static decimal GetRandomSalary(Random rnd) {
return rnd.Next(1000, 3000);
}
public enum Department { Motors, Electronics, Software }
}

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);
}
}
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace BlazorDemo.Data.Northwind {
public partial class Product {
public Product() {
OrderDetails = new HashSet<OrderDetail>();
}
public int ProductId { get; set; }
public string ProductName { get; set; }
public int? SupplierId { get; set; }
public int? CategoryId { get; set; }
public string QuantityPerUnit { get; set; }
public decimal? UnitPrice { get; set; }
public short? UnitsInStock { get; set; }
public short? UnitsOnOrder { get; set; }
public short? ReorderLevel { get; set; }
public bool Discontinued { get; set; }
public bool InStock => !Discontinued;
public virtual Category Category { get; set; }
public virtual Supplier Supplier { get; set; }
public virtual ICollection<OrderDetail> OrderDetails { get; set; }
}
}
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BlazorDemo.Data.Northwind;
using BlazorDemo.DataProviders;
namespace BlazorDemo.Services {
public partial class NwindDataService {
public Task<IEnumerable<Product>> GetProductsAsync(CancellationToken ct = default) {
// Return your data here
}
}
}
using BlazorDemo.Services;
using Microsoft.Extensions.DependencyInjection;
public class Startup {
public void ConfigureServices(IServiceCollection services) {
// ...
services.AddScoped<NwindDataService>();
}
}

Run Demo: List Box – Disabled Items