Skip to main content
All docs
V25.1

v25.1 Release Notes

  • 26 minutes to read

Tip

Visit our website to explore new features across the entire DevExpress product line: What’s New in the Latest Version.

License Keys — New in v25.1

This new release requires every developer/build machine to store a DevExpress license key associated with your account.

DevExpress Unified Installer (Windows) automatically obtains your License Key and places it into its correct location. Run the installer in Repair/Register mode to update your key when necessary. If you used our Unified Installer before license keys were introduced (before v25.1), you should not experience any changes when installing or updating DevExpress products.

If you bypass the DevExpress Unified Installer, you can download your license key and register it in the system manually (via a file on disk or an environment variable). Review detailed instructions in the following help topic: Online NuGet Feeds, CI/CD, and Other Installation Methods (Windows, macOS, Linux).

Legacy Data Grid, ComboBox, Tag Box, and List Box are No Longer Available

To streamline our distribution, we removed the following legacy components from our v25.1 update:

  • DxDataGrid
  • DxComboBoxLegacy
  • DxTagBoxLegacy
  • DxListBoxLegacy

To avoid issues, please check your projects for components from the DevExpress.Blazor.Legacy namespace and migrate to new DevExpress alternatives.

Helpful resources:

If you are still using older versions of DevExpress Blazor components, please contact us via the DevExpress Support Center and let us know how we can help you migrate to newer alternatives.

New Blazor Filter Builder (CTP)

The new DevExpress Blazor Filter Builder UI component allows users to create complex filter criteria with ease. The Blazor Filter Builder component (available as a Community Technology Preview in our v25.1 release cycle) uses our popular CriteriaOperator language and can be connected to any data-aware DevExpress Blazor component.

The DevExpress Blazor Filter Builder ships with the following features/capabilities:

  • Logical Conditions: Supports “And,” “Or,” “Not And,” and “Not Or” logical operators to combine filter conditions.
  • Nested Rules: Allows users to create nested groups with filter conditions for more complex filtering scenarios.
  • Operator Variety: Includes unary, binary, “Between” (for ranges), and “Any Of” (for multiple values) filter operators.
  • Field Configuration: Allows you to define and configure fields available to users. You can display custom captions to improve clarity.
  • Hierarchical Fields: Displays hierarchical fields in a tree-like structure.
  • Data Type-Specific Editors: Generates editors based on field data types.
  • Data Editor Customization: Allows you to customize auto-generated editors using EditSettings (similar to our Blazor Grid component).
  • Foreign Key Editing: Substitutes foreign key values with meaningful text for fields associated with DevExpress Blazor ComboBox editors.

New Blazor Filter Builder

Define Fields

You have full control over data fields the DevExpress Blazor Filter Builder displays to users. Declare fields one by one in Razor markup:

    <DxFilterBuilder>
        <Fields>
            <DxFilterBuilderField FieldName="Name" Caption="Subject" Type="typeof(string)" />
            <DxFilterBuilderField FieldName="OwnerID" Caption="Assignee" Type="typeof(int)" />
            <DxFilterBuilderField FieldName="Status" Caption="Status" Type="typeof(IssueStatus)" />
            <DxFilterBuilderField FieldName="CreatedDate" Caption="Created" Type="typeof(DateTime)" />
            <DxFilterBuilderField FieldName="FixedDate" Caption="Fixed" Type="typeof(DateTime)" />
        </Fields>
    </DxFilterBuilder>

Or iterate through model class properties and define fields in a loop:

<DxFilterBuilder>
    <Fields>
        @foreach(var field in typeof(Invoice).GetProperties()){
            <DxFilterBuilderField FieldName="@field.Name" Type="@field.PropertyType" />
        }
    </Fields>
</DxFilterBuilder>

Create Hierarchical Fields

For complex data models, you can organize nested fields into a tree-like structure. You can also customize field captions displayed in the tree (Caption) and in the resulting filter criteria (CaptionFullPath).

<DxFilterBuilder>
    <Fields>
        <DxFilterBuilderField FieldName="Order.ID" Caption="Order">
            <Fields>
                <DxFilterBuilderField FieldName="Order.Date" Caption="Date" CaptionFullPath="Order.Date" Type="typeof(DateTime)" />
                <DxFilterBuilderField FieldName="Order.Shipped" Caption="Shipped" CaptionFullPath="Order.Shipped" Type="typeof(bool)" />
            </Fields>
        </DxFilterBuilderField>
    </Fields>
</DxFilterBuilder>

New Blazor Filter Builder — Create Hierarchical Fields

Customize Value Editors

While the DevExpress Blazor Filter Builder automatically generates pre-configured data editors based on field types, you can override the default editor used for any field. Use the EditSettings tag to specify a DevExpress Blazor editor for a field and configure editor properties as needed. For instance, you can apply a mask to currency fields to format associated values:

<DxFilterBuilderField FieldName="Total" Type="typeof(decimal)">
    <EditSettings>
        <DxSpinEditSettings Mask="c0" DisplayFormat="c0" />
    </EditSettings>
</DxFilterBuilderField>

Or configure a ComboBox editor for enum fields:

<DxFilterBuilderField FieldName="Status" Type="typeof(IssueStatus)">
    <EditSettings>
        <DxComboBoxSettings Data="StatusList" />
    </EditSettings>
</DxFilterBuilderField>

New Blazor Filter Builder — Customize Value Editors

Configure Foreign Key Editing

For foreign key fields, you can display user-friendly text instead of raw ID values. To display user-friendly text, place DxComboBoxSettings within the EditSettings tag and specify editor data source, value field name, and text field name.

<DxFilterBuilderField FieldName="OwnerID" Caption="Assignee" Type="typeof(int)">
    <EditSettings>
        <DxComboBoxSettings Data="UserList" ValueFieldName="ID" TextFieldName="FullName" />
    </EditSettings>
</DxFilterBuilderField>

Once configured, the field displays a text value instead of the underlying ID even when the ComboBox editor is closed.

New Blazor Filter Builder — Configure Foreign Key Editing

Connect the Filter Builder to a Data Aware Component

You can connect our Blazor Filter Builder to data-aware DevExpress Blazor UI components that support CriteriaOperator syntax:

  • Grid
  • TreeList
  • Pivot Table
  • ListBox

For two-way filter synchronization, use the @bind directive with the FilterCriteria property:

<DxFilterBuilder @bind-FilterCriteria="gridFilter">
    ...
</DxFilterBuilder>

<DxButton Click="ApplyFilter">Apply Filter</DxButton>
<DxButton Click="ClearFilter">Clear Filter</DxButton>

<DxGrid @ref="Grid" FilterCriteriaChanged="OnFilterChanged" ShowFilterRow="true">
    ...
</DxGrid>

@code {
    CriteriaOperator gridFilter;
    IGrid Grid { get; set; }
    void OnFilterChanged(GridFilterCriteriaChangedEventArgs e) {
        gridFilter = e.FilterCriteria;
    }
    void ApplyFilter() {
        Grid.SetFilterCriteria(gridFilter);
    }
    void ClearFilter() {
        Grid.SetFilterCriteria(null);
    }
}

Run Demo

Blazor Themes

Fluent — Official Release

The DevExpress Fluent theme for Blazor is now ready for production use. The new version includes visual enhancements for all DevExpress Blazor components, improved Scheduler UI/UX, and unique icons for all size modes.

Blazor Fluent Theme — Official Release

Fluent — Accent Colors

The Fluent theme now includes 11 built-in accent color options:

Blazor Fluent Theme — Built-in Accent Colors

Developers can also configure custom accent colors to match user preferences or brand colors:

@DxResourceManager.RegisterTheme(Themes.Fluent.Clone(properties => {
    properties.SetCustomAccentColor("#107c41");
}))

Blazor Fluent Theme — Custom Accent Colors

New Theme API

Register Theme

You can register DevExpress Blazor themes using our new ResourceManager.RegisterTheme(ITheme) method:

<head>
    @*...*@
    @DxResourceManager.RegisterTheme(Themes.Fluent)
</head>

This method automatically adds all required resources for the selected theme and manages CSS browser cache between DevExpress versions.

Clone and Customize Themes

You can now clone built-in DevExpress themes using the Clone() method. This method allows you to add your own CSS files to a theme and load them when this theme is applied. For themes based on Fluent, you can also customize theme properties as follows:

  • Light or dark mode
  • Built-in or custom accent color
<head>
    @*...*@
    @DxResourceManager.RegisterTheme(Themes.Fluent.Clone(properties => {
        properties.Name = "Fluent Light Purple";
        properties.Mode = ThemeMode.Light;
        properties.AccentColor = ThemeFluentAccentColor.Purple;
        properties.ApplyToPageElements = true;
        properties.AddFilePaths("FluentPurpleStyles.css");
    }))
</head>

Switch Themes at Runtime

With our new theme APIs, you can easily switch between multiple themes at runtime. To change an application theme, inject IThemeChangeService into a Razor page and call the SetTheme method:

@inject IThemeChangeService ThemeChangeService
@rendermode InteractiveServer
<DxButton Text="Blazing Berry" Click="() => HandleClick(Themes.BlazingBerry)" />
<DxButton Text="Fluent" Click="() => HandleClick(Themes.Fluent)" />
<DxButton Text="Fluent Dark" Click="() => HandleClick(AppThemes.FluentDark)" />
@code {
    void HandleClick(ITheme theme) {
        ThemeChangeService.SetTheme(theme);
        // ...
    }
    public class AppThemes {
        public static ITheme FluentDark = Themes.Fluent.Clone(properties => {
            properties.Name = "FluentDark";
            properties.Mode = ThemeMode.Dark;
        });
        public static List<ITheme> All { get; private set; } = new List<ITheme>() {
            Themes.BlazingBerry,
            Themes.Fluent,
            FluentDark
        };
    }
}

Updated Fluent UI Kit for Figma

The DevExpress Blazor Fluent UI Kit was updated. It now includes more than 50 ready-to-use components that replicate look and feel of our controls. Using Blazor UI Kit, teams can build design prototypes faster and ensure that mockups align with capabilities/styling of DevExpress Blazor components.

Updated Fluent UI Kit for Figma

App Showcase Demo

New CRM, Analytics, and Scheduling/Planning modules (built with our Blazor Grid, TreeList, Scheduler, ListBox, ComboBox, Charts, and other DevExpress Blazor UI components).

Our showcase demo utilizes InteractiveAuto render mode, introduced in .NET 8 — using Blazor Server for fast initial load and seamlessly transitioning to WebAssembly (WASM) for optimal speed and responsiveness.

The application uses our new Fluent theme with light/dark mode support. Each module is built with reusable code, so you can easily adapt/integrate module components into your next DevExpress-powered Blazor project.

App Showcase Demo

To explore the capabilities of the demo, open our locally installed showcase demo: C:\Users\Public\Public Documents\DevExpress Demos 25.1\Components\Blazor\BlazorDemo.Showcase or visit Blazor Showcase Demo.

New Project Templates

We extended Blazor Project Templates in our Cross-IDE Project Template Kit (available for Visual Studio and VS Code). ASP.NET Core Blazor Application template now includes the following options:

  • Global interactivity configuration
  • Built-in authentication UI
  • Theme and Size Mode selection
  • Resource registration for DevExpress Blazor Rich Text Editor, Pivot Table, and PDF Viewer
  • AI service setup

The Project Template Kit also includes Blazor Hybrid templates targeting MAUI, WinForms, and WPF.

Cross-IDE Project Template Kit

Performance Enhancements

Blazor Package Size Optimization

We reorganized CSS files used across DevExpress Blazor Themes and removed Bootstrap dependencies where possible. As a result, the total size of Blazor Theme resources was reduced by 80% (for instance a DevExpress-powered Blazor application that once required 218 MB (in v24.2) now only needs 79 MB).

Blazor Grid, Pivot Table, and Scheduler — Faster Rendering

In v25.1, we optimized the internal structure of the DevExpress Blazor Grid, Pivot Table, and Scheduler component. This change helps reduce the number of rendered elements, improves component load time, and minimizes client-server traffic (transferred via WebSocket after UI interactions).

Blazor Grid — Fixed Column Rendering

We optimized style calculations for fixed columns to increase initial rendering speed of the DevExpress Blazor Grid component (especially when displaying many columns).

Blazor Grid — Fixed Column Rendering

Blazor Scheduler — Improved UI Responsiveness

We optimized key aspects of the DevExpress Scheduler UI component to deliver smoother performance in Blazor Server apps (especially over slower connections). Enhancements include:

  • Faster popup opening in Date and Resource Navigators
  • Improved responsiveness during appointment drag and select operations
  • Faster opening of the appointment tooltip and compact/extended appointment forms
  • Improved performance for creating, updating, and deleting appointments
  • Smoother resource switching and date interval changes

Blazor Toolbar, Ribbon & Context Menu — Faster Popup Opening

We reduced server-client message traffic for our popup menus. As a result, menus now open 20–70% faster in Blazor Server apps (based on network conditions and item count). These improvements apply to DevExpress Blazor Toolbar, Ribbon, and Context Menu components, as well as other components that use our menus internally.

Blazor Rich Text Editor & HTML Editor — Popup Optimization

DevExpress Blazor Rich Text Editor and HTML Editor components in Blazor Server apps now open integrated Ribbon menus and context menus faster. We also optimized AI-powered command initialization and significantly improved context menu performance when AI features are enabled.

Blazor AI Chat

Prompt Suggestions

Our Blazor AI Chat component supports prompt suggestions – hints that guide users to possible actions. The component displays prompt suggestions (hint bubbles) when the chat area is empty.

Follow the steps below to enable and configure prompt suggestions:

  1. Populate the component’s PromptSuggestions property with DxAIChatPromptSuggestion objects (hint bubbles).
  2. Specify bubble content using Title and Text properties.
  3. Use the PromptMessage property to specify the text to be displayed in the input field after a user clicks the corresponding suggestion.
@using DevExpress.AIIntegration.Blazor.Chat

<DxAIChat>
    <PromptSuggestions>
        <DxAIChatPromptSuggestion Title="Tell me a joke"
                                  Text="Take a break and enjoy a quick laugh"
                                  PromptMessage="Tell me a joke." />
        @* ... *@
    </PromptSuggestions>
</DxAIChat>

Blazor AI Chat — Prompt Suggestions

Run Demo

File Attachments

Users can now attach files when sending messages to our Blazor AI Chat. Set the DxAIChat.FileUploadEnabled property to true to activate file upload functionality. You can validate file size/type/extension and limit file list size using the nested DxAIChatFileUploadSettings component.

You can also use AIChatUploadFileInfo class properties to send messages with file attachments in code (via the SendMessage method) or access and process uploaded files in a MessageSent event handler.

<DxAIChat FileUploadEnabled="true">
    <AIChatSettings>
        <DxAIChatFileUploadSettings MaxFileSize="40000000"
                                    MaxFileCount="3"
                                    AllowedFileExtensions="@(new List<string> {".jpeg", ".jpg", ".pdf"})"
                                    FileTypeFilter="@(new List<string> { "image/*", "application/pdf"})">
        </DxAIChatFileUploadSettings>
    </AIChatSettings>
</DxAIChat>

Blazor AI Chat — File Attachments

Run Demo

Stop Chat Message Generation

Our Blazor AI Chat component allows users to stop chat message generation before it is complete. You can also use the CancellationToken argument property in a MessageSent event handler to process cancellations in code.

Blazor AI Chat — Stop Chat Message Generation

API to Reuse an Existing OpenAI Assistant

You can now connect our Blazor AI Chat to an initialized OpenAI Assistant. This allows you to use a single OpenAI Assistant instance to initiate multiple tasks within a single app. To connect the chat to an existing OpenAI Assistant, pass its identifier to the SetupAssistantAsync method as a parameter.

<DxAIChat Initialized="Initialized">
    @* ... *@
</DxAIChat>

@code {
    async Task OnChatInitialized(IAIChat chat) {
        // ...
        string assistantId = await assistantCreator.CreateAssistantAsync(data, fileName);
        await chat.SetupAssistantAsync(assistantId);
    }
}

Blazor Grid

Row-based Drag & Drop Enhancements

Users can now move rows between master and detail areas of the DevExpress Blazor Grid UI component via drag & drop operations. To enable this behavior, configure master and detail Blazor Grid components as follows:

Blazor Grid & TreeList

PDF Export

DevExpress Blazor Grid and TreeList UI components now support PDF export. This feature allows you to generate PDF documents that reflect the current filter, sort order, and group settings. Exported PDF documents include the following elements:

  • Data columns
  • Group rows and summaries
  • Total summaries

When exporting to PDF, our Blazor Grid and TreeList components maintain column order, captions, value format, and text alignment. Use the ExportToPdf method parameter to exclude specific rows/columns from export operations, add headers/footers, and/or style the document.

Grid & TreeList - PDF Export

Run Demo: Grid Run Demo: TreeList

Keyboard Support Enhancements

  • Filter Row: Users can now enter a new filter value even if a cell editor is inactive (no need to press Enter first).
  • Edit Row: The Enter/Esc key now saves/discards changes made in the edited row and exits edit mode.
  • Cell Editing: If the EditOnKeyPress property is enabled, users can begin typing a new value into a focused cell (replacing the previous value). The EnterKeyDirection option specifies where focus moves after a user presses the Enter key (moves within a row/column or stays in place).

This new Excel-inspired behavior speeds up tabular data shaping/editing when using the keyboard.

Grid & TreeList - Keyboard Support Enhancements

Run Demo: Grid Run Demo: TreeList

Blazor TreeList

Filtering and Sorting by Display Text

The DevExpress Blazor TreeList UI component can now sort/filter column data by text (instead of actual values). This behavior is especially useful for foreign key columns, as they display data from external collections.

To activate this feature, set SortMode and FilterMode properties to DisplayText. The following code allows users to sort employees alphabetically and filter them by John (rather than by 123):

<DxTreeList Data="TreeListData" KeyFieldName="Id" ParentKeyFieldName="ParentId" ShowFilterRow="true">
    <Columns>
        <DxTreeListDataColumn FieldName="Name" Caption="Task" />
        <DxTreeListDataColumn FieldName="EmployeeId" Caption="Assigned To"
                              SortMode="TreeListColumnSortMode.DisplayText"
                              FilterMode="TreeListColumnFilterMode.DisplayText" >
            <EditSettings>
                <DxComboBoxSettings Data="Employees" ValueFieldName="EmployeeId" TextFieldName="FullName" />
            </EditSettings>
            <FilterRowCellTemplate>
                <DxTextBox Text="@FilterCriteriaText" TextChanged="newText => UpdateCriteria(newText, context)" />
            </FilterRowCellTemplate>
        </DxTreeListDataColumn>
        <DxTreeListDataColumn FieldName="StartDate" />
        <DxTreeListDataColumn FieldName="DueDate" />
    </Columns>
</DxTreeList>
@code {
    string FilterCriteriaText { get; set; }
    void UpdateCriteria(string newText, TreeListDataColumnFilterRowCellTemplateContext context) {
        if (!string.IsNullOrEmpty(newText))
            context.FilterCriteria = new FunctionOperator(FunctionOperatorType.Contains, new OperandProperty(context.DataColumn.FieldName), newText);
        else
            context.FilterCriteria = null;
    }
    //...
}

TreeList - Display Text Support

The DevExpress Blazor TreeList UI component includes a progressive case-insensitive search option (allows you to locate matched text as you type). When you type within the search box, our Blazor TreeList filters data rows, displays those that match the search string, and highlights search results.

Additional features include:

  • Support for special characters.
  • Configurable input delay.
  • Search box placeholder (null text) support.
  • Ability to exclude specific columns from search operations.
  • Built-in search text parse modes.
  • Ability to specify search text in code (Search API).

And yes, you can customize search box appearance settings, render the search box from a template, or use an external editor.

TreeList - Search

Read Tutorial: Documentation Run Demo

Blazor Charts

Visual Range and Zoom API Enhancements

The DevExpress Blazor DxChart component allows you to react to axis visual range changes using the VisualRangeChanged event. In a handler, you can obtain the following information:

  • Change source (zoom/pan action in UI or a method call)
  • Affected (changed range) Axis (argument or value)
  • Current and previous ranges
<DxChart Data="forecasts"
         VisualRangeChanged="@OnVisualRangeChanged">
    <DxChartAreaSeries ArgumentField="@((WeatherForecast v) => v.Date)"
                       ValueField="@((WeatherForecast v) => v.TemperatureC)" />
    <DxChartZoomAndPanSettings ArgumentAxisZoomAndPanMode="ChartAxisZoomAndPanMode.Both"
                               ValueAxisZoomAndPanMode="ChartAxisZoomAndPanMode.Both" />
</DxChart>

@code {
    void OnVisualRangeChanged(ChartVisualRangeChangedEventArgs args) {
        var previousRange = args.PreviousRange.
        var currentRange = args.CurrentRange;
        ShowDetailDialog(PreviousRange, CurrentRange);
    }
    // ...
}

You can also use the following methods to modify axis visual ranges at runtime:

Run Demo

Series Label API Enhancements

With v25.1, we expanded the list of available series label options. The DxChartSeriesLabel component now includes the following properties that affect pie series labels:

TextOverflow | WordWrap
Specify how the Pie Chart displays text for overflowing labels.
RadialOffset
Shifts pie series labels radially away from or towards the chart center.
<DxPieChart Data="@DataSource">
    <DxPieChartSeries ArgumentField="@((StatisticPoint v) => v.Country)"
                      ValueField="@((StatisticPoint v) => v.Population24)"
                      Name="2024">
        <DxChartSeriesLabel Visible="true"
                            RadialOffset="15"
                            TextOverflow="ChartTextOverflow.None"
                            WordWrap="ChartWordWrap.BreakWord"
                            FormatPattern="{argument}: {value}">
            <DxChartSeriesLabelConnector Visible="true" />
        </DxChartSeriesLabel>
    </DxPieChartSeries>
</DxPieChart>

Legend Click Events

v25.1 includes DxChart.LegendClick, DxPolarChart.LegendClick, and DxPieChart.LegendClick events. Handle these events to execute custom logic when users click legend items.

<DxChart Data="@DataSource"
         @ref="chart"
         Width="1200px"
         Height="300px"
         SeriesSelectionMode="ChartSelectionMode.Single"
         LegendClick="@OnChartLegendClick">
    <DxChartBarSeries ArgumentField="@((StatisticPoint v) => v.Country)"
                      ValueField="@((StatisticPoint v) => v.Population24)"
                      Name="2024" />
    <DxChartLineSeries ArgumentField="@((StatisticPoint v) => v.Country)"
                       ValueField="@((StatisticPoint v) => v.Population23)"
                       Name="2023" />
</DxChart>

@code {
    DxChart<StatisticPoint> chart;

    public void OnChartLegendClick(ChartLegendClickEventArgs args) {
        if (args.Series != null) {
            var SeriesName = args.Series.Name;
            var TotalPopulation = SeriesName == "2023" ? DataSource.Select(x => x.Population23).Sum() : DataSource.Select(x => x.Population24).Sum();
            ShowDetailDialog(SeriesName, TotalPopulation);
        }
    }
    // ...
}

Automatic Line Series Order

DevExpress Blazor Charts support configurable ordering of line series connectors. Use the following properties to specify whether connectors follow visual argument order or original data source order:

Set the Sorted property to true to prevent connector intersections and reversals.

Set the Sorted property to false to improve performance if your data is already sorted. You can also use it to plot raw experimental data when a specific sequence is important.

Sorted properties only affect the appearance of line series with numeric or date arguments.

<DxChart Data="DataSource"
         Sorted="true">
    <DxChartTitle Text="Sorted line chart" />
    <DxChartLegend Visible="false" />
    <DxChartLineSeries ArgumentField="@((SaleInfo s)=>s.Date)"
                       ValueField="@((SaleInfo s)=>s.Amount)" />
</DxChart>

@code {
    List<SaleInfo> DataSource { get; set; } = new List<SaleInfo>();

    protected override void OnInitialized() {
        DataSource = Data.Sales.GetMonthlySales();
    }
}

Sorted Line Series

Blazor Data Editors

Blazor ComboBox — Set Data Load Mode

The DevExpress Blazor ComboBox allows you to manage data source interactions using DataLoadMode. Since v24.1, our Blazor ComboBox caches data to reduce frequent database requests. You can now set DataLoadMode to OnDemand (similar to behaviors available prior to v24.1). This option allows the ComboBox to fetch data from the data source each time the dropdown activates. When this option is used, our Blazor ComboBox does not preload data when the page loads (improving initial page load speed).

Blazor Calendar & Date Edit

Picker View

Our Blazor Calendar and Date Edit components allow you to limit selection to months, years, or decades. This can be useful for forms and fields that do not require a specific date value.

Picker View

Read Tutorial: Calendar - Documentation Read Tutorial: Date Edit - Documentation Run Demo: Calendar - Month/Year Picker View Run Demo: Date Edit - Month/Year Picker View

Blazor Date Edit & Time Edit

Custom Increment Step

Time rollers (scroll pickers) for both our Blazor Date Edit and Time Edit components support custom increment steps. This allows you to display fewer values (e.g., an hour in 15 minute intervals) when precise selection is not necessary.

<DxTimeEdit Time="DateTime.Now" 
            ScrollPickerFormat="h m s"
            HourIncrement="2" 
            MinuteIncrement="15"
            SecondIncrement="15" />

<DxDateEdit Time="DateTime.Now" 
            ScrollPickerFormat="h m s"
            TimeSectionHourIncrement="2" 
            TimeSectionMinuteIncrement="15"
            TimeSectionSecondIncrement="15" />

Scroll Picker - Custom Increment

Read Tutorial: Date Edit - Documentation Read Tutorial: Time Edit - Documentation

Scroll Picker Localization

You can now localize scroll picker column captions in both Blazor Date Edit and Time Edit components.

Scroll Picker - Localization

Blazor List Box

Select All

The DevExpress Blazor List Box can now display a Select All checkbox and allow users to select/deselect all list items simultaneously. To display this checkbox, enable multiple selection mode and set ShowSelectAllCheckbox and ShowCheckboxes properties to ‘true’.

The following code adds a List Box to a DropDown Box and activates the Select All option for the List Box.

<DxDropDownBox @bind-Value="Value"
               QueryDisplayText="QueryText"
               ... >
    <DropDownBodyTemplate>
        <DxListBox Data="@ListBoxData"
                   Values="@(GetListBoxValues(context.DropDownBox))"
                   ValuesChanged="@(values => ListBoxValuesChanged(values, context.DropDownBox))"
                   SelectionMode="ListBoxSelectionMode.Multiple"
                   ShowCheckboxes="true"
                   ShowSelectAllCheckbox="true"
                   ... >
        </DxListBox>
    </DropDownBodyTemplate>
</DxDropDownBox>

@code {
    // ...
    string QueryText(DropDownBoxQueryDisplayTextContext arg) {
        var names = (arg.Value as IEnumerable<Employee>)?.Select(x => x.LastName);
        return names != null ? string.Join(",", names) : string.Empty;
    }
    IEnumerable<Employee> GetListBoxValues(IDropDownBox dropDownBox) {
        return dropDownBox.Value as IEnumerable<Employee>;
    }
    void ListBoxValuesChanged(IEnumerable<Employee> values, IDropDownBox dropDownBox) {
        dropDownBox.BeginUpdate();
        dropDownBox.Value = values;
        dropDownBox.EndUpdate();
    }
}

List Box - Select All

Run Demo: DropDown Box and Multiple Selection List Box

API Enhancements

  • SearchBoxNullText - Specifies the prompt text displayed in the search box when it is empty.
  • SearchBoxInputDelay - Specifies the delay between the last input in the search box and when the List Box displays matching values.

Column-Specific Cell Templates

DevExpress Blazor ComboBox, List Box, and TagBox now support customization of cell appearance within individual columns.

A column-specific cell template is specified via the CellDisplayTemplate property. This property accepts a cell context and allows you to format cell data, apply styles, and add custom HTML markup.

The CellDisplayTemplate property can be used alongside the ColumnCellDisplayTemplate property of the corresponding DevExpress Blazor component. If both templates are defined, the column-specific template takes precedence over the global ColumnCellDisplayTemplate for cells within a given column. Use this mechanism to define a common template for every column and then override it for columns that require unique formatting.

<DxTagBox Data="Subscriptions.Plans"
            @bind-Values="SelectedPlans"
            EditFormat="{0}" style="width:500px;">
    <Columns>
        <DxListEditorColumn FieldName="Name" Caption="Plan">
            <CellDisplayTemplate>
                <div style="text-align: left;">
                    <b>@context.Value Subscription</b>
                </div>
            </CellDisplayTemplate>
        </DxListEditorColumn>
        <DxListEditorColumn FieldName="PriceMonth" Caption="Month" />
        <DxListEditorColumn FieldName="PriceQuarter" Caption="Quarter" />
        <DxListEditorColumn FieldName="PriceYear" Caption="Year" />
    </Columns>
    <ColumnCellDisplayTemplate>
        <div style="text-align: right;">
            @($"{context.Value:C}")
        </div>
    </ColumnCellDisplayTemplate>
</DxTagBox>

@code {
    IEnumerable<SubscriptionPlan> SelectedPlans { get; set; }
}

Combined Cell Templates in TagBox

Blazor Pivot Table

Filter Data

Our Blazor Pivot Table allows you to add filter UI capabilities to your application and to filter Pivot Table data in code.

Read Tutorial: Filter Data

Filter UI

Users can apply filters to row and column fields. Field headers display filter menu buttons with access to filter menus. These filter menus display all unique field values and allow users to select desired values. Filter menus include a built-in search box and a Select All checkbox.

Pivot Table - Filter UI

We also give you the ability to define special filter fields. Though these field data are not displayed directly in the main table view, users can filter Pivot Table data based on their values. For example, you might not display car modifications in the table, but need to display cars with a specific modification. You can add the Modification field as a filter field and use it to filter data.

Users can easily access these filter fields in the Filter Header Area, invoke Filter Menus, and select/deselect field values accordingly.

Pivot Table - Filter Fields

v25.1 also ships with APIs designed to control filter UI capabilities and customize filter menus. For example, you can handle the CustomizeFilterMenu event to customize, add, or remove filter menu items. You can also use FilterMenuTemplate or FieldFilterMenuTemplate to specify custom content for filter menus. The following code categorizes fuel efficiency (MPG City field) into three discrete groups (High, Medium, and Low) to enable filtering based on these categories.

<DxPivotTable Data="@PivotData">
    <Fields>
       <DxPivotTableField Field="@nameof(VehiclesData.TrademarkItem.MPGCity)"
                            Name="@MPGCityName"
                            Area="@PivotTableArea.Filter">
            <FilterMenuTemplate>
                <MPGCustomFiltersList FilterMenuContext="context" Filters="@MPGCityFilterItems"></MPGCustomFiltersList>
            </FilterMenuTemplate>
    </Fields>
</DxPivotTable>

@code {
    // ...
    IReadOnlyList<MPGCustomFilterItem> GetMPGCityFilterItems() {
        return new List<MPGCustomFilterItem> {
            new MPGCustomFilterItem { Text = "High",
                                      Key = 0,
                                      FilterCriteria = CriteriaOperator.Parse($"[{MPGCityName}]>25") },
            new MPGCustomFilterItem { Text = "Medium",
                                      Key = 1,
                                      FilterCriteria = CriteriaOperator.Parse($"[{MPGCityName}]>=15 AND [{MPGCityName}]<=25") },
            new MPGCustomFilterItem { Text = "Low",
                                      Key = 2,
                                      FilterCriteria = CriteriaOperator.Parse($"[{MPGCityName}]<15") }
        };
    }
}

Pivot Table - Filter Menu Template

Filter API

The Pivot Table allows you to apply filters in code. You can create filter criteria based on specific values, ranges, or conditions, obtain this criteria, or clear the filter. For example, you might filter sales data to display transactions from a certain region or within a specific date range.

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

<DxPivotTable Data="SalesData" @ref="PivotTable"> @*...*@ </DxPivotTable>

<p>Filter Criteria: <b>@PivotTable?.GetFilterCriteria()?.ToString()</b></p>

@code {
    // ... 
    void OnItemClick(ToolbarItemClickEventArgs e) {
        switch (e.ItemName) {
            case "_setFilterCriteria":
                PivotTable.SetFilterCriteria(new BinaryOperator(nameof(Sales.SaleInfo.Region), "North America", BinaryOperatorType.Equal));
                break;
            case "_clearFilterCriteria":
                PivotTable.ClearFilter();
                break;
        }
    }
}

Run Demo: Filter Data

Field Customization

With v25.1, our Blazor Pivot Table allows users to intuitively customize data layout by dragging fields between different areas (Rows, Columns, Data, and Filter) or within the same area.

In addition, a built-in Field List offers a powerful alternative for managing Pivot Table structure. Users can reorder fields, move fields across different areas, and display/hide them from the Field List. These interactive features allow users to configure/personalize the Pivot Table, without modifying the underlying data source or code.

Pivot Table - Field Customization

To display the Field List, use the ShowFieldList method. The following code adds a toolbar item that invokes the Field List.

<DxToolbar ItemRenderStyleMode="ToolbarRenderStyleMode.Contained">
    <Items>
        <DxToolbarItem Alignment="ToolbarItemAlignment.Right" Text="Show Field List" RenderStyle="ButtonRenderStyle.Secondary" IconCssClass="pivot-table-icon-field-list" Click="FieldListButton_Click" />
    </Items>
</DxToolbar>

@code {
    object PivotData { get; set; }
    IPivotTable PivotTable { get; set; }

    void FieldListButton_Click() {
        PivotTable.ShowFieldList();
    }
}

Read Tutorial: Field Customization in the UI Run Demo: Field Customization

Persistent Layout

The DevExpress Blazor Pivot Table allows you to save and restore layout settings. A saved layout object includes the following data:

  • field settings (field area, field order, field sort order, field visibility)
  • filter criteria
  • expand/collapse state of rows and columns

This option allows users to customize our Blazor Pivot Table to match personal preferences and reload the same layout each time they log into your DevExpress-powered app (said differently, users no longer need to reconfigure Pivot Table field layout, reapply filters, and/or sorting).

Use the following APIs to persist Pivot Table layout:

<DxButton Text="Save Layout" Click="OnSaveClick" />
<DxButton Text="Load Layout" Click="OnLoadClick" />

<DxPivotTable @ref="@PivotTable"
              Data="@PivotData"
              LayoutAutoLoading="PivotTable_LayoutAutoLoading"
              LayoutAutoSaving="PivotTable_LayoutAutoSaving">
            @*...*@
</DxPivotTable>
@code {
    //...
     async Task PivotTable_LayoutAutoLoading(PivotTablePersistentLayoutEventArgs e) {
        e.Layout = await LoadLayoutFromLocalStorageAsync();
    }
    async Task PivotTable_LayoutAutoSaving(PivotTablePersistentLayoutEventArgs e) {
        await SaveLayoutToLocalStorageAsync(e.Layout);
    }
    // Refer to https://docs.microsoft.com/en-us/aspnet/core/blazor/state-management
    // to learn more about Blazor state management
    // In Blazor Server apps, prefer ASP.NET Core Protected Browser Storage
    async Task<PivotTablePersistentLayout> LoadLayoutFromLocalStorageAsync() {
        try {
            var json = await JSRuntime.InvokeAsync<string>("localStorage.getItem", LocalStorageKey);
            return JsonSerializer.Deserialize<PivotTablePersistentLayout>(json);
        } catch {
            // Mute exceptions for the server prerender stage
            return null;
        }
    }
    async Task SaveLayoutToLocalStorageAsync(PivotTablePersistentLayout layout) {
        try {
            var json = JsonSerializer.Serialize(layout);
            await JSRuntime.InvokeVoidAsync("localStorage.setItem", LocalStorageKey, json);
        } catch {
            // Mute exceptions for the server prerender stage
        }
    }
    async Task RemoveLayoutFromLocalStorageAsync() {
        try {
            await JSRuntime.InvokeVoidAsync("localStorage.removeItem", LocalStorageKey);
        } catch {
            // Mute exceptions for the server prerender stage
        }
    }
    async Task ReloadPageButton_ClickAsync() {
        await JSRuntime.InvokeVoidAsync("location.reload");
    }
    async Task ResetLayoutButton_ClickAsync() {
        await RemoveLayoutFromLocalStorageAsync();
        await JSRuntime.InvokeVoidAsync("location.reload");
    }
    void OnSaveClick() {
        Layout = MyPivotTable.SaveLayout();
    }

    void OnLoadClick() {
        MyPivotTable.LoadLayout(Layout);
    }
}

Pivot Table - Save and Restore Layout

Read Tutorial: Save and Restore Layout Run Demo: Save and Restore Layout

Blazor Rich Text Editor

Zoom

Our Rich Text Editor‘s built-in Ribbon includes a UI command designed to zoom in and out of documents.

Blazor Rich Text Editor — Zoom Command

Set the DxRichEdit.AllowZoom property to false to hide the Ribbon command and disable zoom functionality. Regardless of the AllowZoom property value, you can use the ZoomLevel property to zoom the document in code.

<DxRichEdit ZoomLevel="0.7" />

Run Demo

Blazor Scheduler

Toolbar Customization

The DevExpress Blazor Scheduler allows you to define custom toolbar items and customize the following built-in items:

Customization options include:

  • Position and alignment of toolbar items.
  • Enabled, Visible, Tooltip, and Render Style properties.

Use the ToolbarItems tag to modify the collection of visible toolbar items. Declare DxToolbarItem objects to add custom items to this collection. Alternatively, disable the ShowToolbarArea property to hide the toolbar entirely.

<DxScheduler @bind-StartDate="@StartDate"
             DataStorage="@DataStorage">
    <Views>
        <DxSchedulerTimelineView Duration="@CurrentDuration">
            <Scales>
                <DxSchedulerTimeScale Unit="@SchedulerTimeScaleUnit.Day" UnitCount="1"></DxSchedulerTimeScale>
                <DxSchedulerTimeScale Unit="@SchedulerTimeScaleUnit.Hour" UnitCount="6"></DxSchedulerTimeScale>
            </Scales>
        </DxSchedulerTimelineView>
    </Views>
    <ToolbarItems>
        <DxSchedulerPreviousIntervalToolbarItem />
        <DxSchedulerNextIntervalToolbarItem />
        <DxSchedulerTodayToolbarItem />
        <DxToolbarItem GroupName="ScaleDuration"
                       Text="1 day"
                       Click="@((i) => CurrentDuration = TimeSpan.FromHours(24))"
                       Checked="@(CurrentDuration == TimeSpan.FromHours(24))"
                       BeginGroup="true"
                       Alignment="ToolbarItemAlignment.Right"></DxToolbarItem>
        <DxToolbarItem GroupName="ScaleDuration"
                       Text="2 days"
                       Click="@((i) => CurrentDuration = TimeSpan.FromHours(48))"
                       Checked="@(CurrentDuration == TimeSpan.FromHours(48))"></DxToolbarItem>
        <DxToolbarItem GroupName="ScaleDuration"
                       Text="3 days"
                       Click="@((i) => CurrentDuration = TimeSpan.FromHours(72))"
                       Checked="@(CurrentDuration == TimeSpan.FromHours(72))"></DxToolbarItem>
    </ToolbarItems>
</DxScheduler>

@code {
    DateTime StartDate { get; set; } = DateTime.Today;
    TimeSpan CurrentDuration = @TimeSpan.FromHours(48);
}

Scheduler - Toolbar with Custom Items

Run Demo: Toolbar Customization

Appointment Form and Tooltip Customization

You can now specify the size of Scheduler pop-up elements: appointment form (compact/extended) and tooltips. You can also apply CSS classes to these elements.

Our extended appointment form supports drag and resize operations (it is now easier to view the entirety of a calendar without discarding changes).

To incorporate such customizations into your Blazor Scheduler, declare a corresponding object in the PopupSettings tag and specify desired options:

<style>
    .custom-style {
        font-style: italic;
    }
</style>

<DxScheduler StartDate="DateTime.Today"
             DataStorage="DataStorage">
    <Views>
        <DxSchedulerDayView ShowWorkTimeOnly="true" />
    </Views>
    <PopupSettings>
        <DxSchedulerCompactFormSettings MaxHeight="600px"
                                        CssClass="custom-style" />
        <DxSchedulerFormSettings Width="1200px"
                                 AllowDrag="true" />
        <DxSchedulerTooltipSettings MinWidth="300px" />
    </PopupSettings>
</DxScheduler>

UI/UX Enhancements

We reworked the design of the Devexpress Blazor Scheduler as follows:

  • A new render style mode for built-in toolbar items. We changed render style mode to Plain.
  • New icons used for the Today button and each view selector (Day, Work Week, Month, Timeline).
  • New appointment label colors for the Fluent theme. We updated default label colors, replacing bright colors with a pastel palette. This modification was designed to improve visual clarity and reduces eye strain.
  • New status styles for the Fluent theme. Appointment statuses now use styles similar to those of Microsoft Outlook.

With the following changes, you can create compact DevExpress-powered interfaces designed to maximize on-screen information display and page layouts that are visually approachable:

  • Appointment captions, time spans, and descriptions are now cropped if they do not fit into allocated space. Users can see cropped content within a default browser tooltip.
  • We replaced a button group with a dropdown button for the view selector. This change allows you to add additional custom items to the toolbar.
  • You can now change visibility of appointment time spans. Use the ShowAppointmentDateTimeRange property to save even more space.

Blazor Windows

Lazy Loading and Pre-Rendering for Popups

DevExpress Blazor popup windows, popup dialogs, fly-outs, and drop-down windows allow you to control when content is rendered. Use the ContentLoadMode property to select the render mode that best suits your needs:

  • Use OnEveryShow to re-render popup content into the DOM each time the popup is opened and remove it from the DOM when the popup is closed (this is how popups were rendered in previous versions). Recommended for popups with frequently updated content, or when the same popup is used to display different data based on context.
  • Use OnComponentLoad to pre-render content on page load for instant appearance.
  • Use OnFirstShow to render popup content when the popup is opened for the first time (lazy loading). This enhances page load speed and reduces initial resource consumption (works best for fixed-content popups that may not be opened by the user, such as settings dialogs or static help).
<DxWindow @bind-Visible="ConsentVisible"
          HeaderText="We value your privacy"
          ContentLoadMode="PopupContentLoadMode.OnComponentLoad"
          Width="max(25vw, 250px)">
    <p>We use cookies to enhance your browsing experience.
       By clicking "Accept All", you consent to our use of cookies.</p>
    <DxButton Text="Accept All" />
</DxWindow>

@code {
    bool ConsentVisible { get; set; } = false;

    protected override void OnInitialized() {
        ConsentVisible = true;
    }
}
See Also