blazor-405374-components-data-editors-combobox-appearance-customization-templates.md
ComboBox templates are RenderFragment<TValue> type properties. These render fragments can contain both markup and other Razor components. A template’s Razor markup can access an implicit parameter named context. This parameter is derived from the TValue type and contains template-related members.
You can use the Context attribute to change the parameter name. This name change is essential when you nest components that contain RenderFragment<TValue> properties, otherwise, the following error can occur: The child content element ‘ChildContent’ of component ‘X’ uses the same parameter name (‘context’) ….
The ItemDisplayTemplate property allows you to customize the appearance of ComboBox items. The property accepts a ComboBoxItemDisplayTemplateContext<TData> object as the context parameter. You can use the parameter’s members to obtain item information:
The following code snippet uses the ItemDisplayTemplate property to display ComboBox items in a card-like view. Each item shows an employee’s first name, last name, photo, and phone number.
@inject NwindDataService NwindDataService
<DxComboBox Data="@Data"
@bind-Value="@Value"
CssClass="cw-480"
InputId="cbItemTemplate">
<ItemDisplayTemplate>
<div class="combobox-item-template">
<div class="combobox-item-template-text">
<span>@context.DataItem.FullName</span>
<span class="combobox-item-template-employee-phone">@context.DataItem.HomePhone</span>
</div>
</div>
</ItemDisplayTemplate>
</DxComboBox>
@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";
}
}
.combobox-item-template {
display: flex;
align-items: center;
}
.combobox-item-template > img {
border-radius: 50%;
width: 2rem;
height: 2rem;
}
img + .combobox-item-template-text {
margin-left: 1rem;
}
.combobox-item-template-text {
display: flex;
flex-flow: column;
}
.combobox-item-template-employee-phone {
opacity: 0.65;
}
public partial class Employee {
public Employee() {
this.Orders = new List<Order>();
}
public int EmployeeId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string Title { get; set; }
public string TitleOfCourtesy { get; set; }
public Nullable BirthDate { get; set; }
public Nullable HireDate { 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 HomePhone { get; set; }
public string Extension { get; set; }
public byte[] Photo { get; set; }
public string Notes { get; set; }
public Nullable<int> ReportsTo { get; set; }
public string PhotoPath { get; set; }
public string GroupName { get; set; }
public virtual ICollection<Order> Orders { get; set; }
public string Text => $"{FirstName} {LastName} ({Title})";
public string FullName => $"{FirstName} {LastName}";
public string ImageFileName => $"employees/{EmployeeId}.jpg";
}
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<Employee>> GetEmployeesAsync(CancellationToken ct = default) {
// Return your data here
}
}
}
public class Startup {
public void ConfigureServices(IServiceCollection services) {
// ...
services.AddScoped<NwindDataService>();
}
}
Run Demo: ComboBox - Item Display Template
The EditBoxDisplayTemplate property allows you to customize the appearance of a ComboBox item displayed in the edit box.
The most popular usage scenario for the EditBoxDisplayTemplate property is to show item icons in the edit box.
<DxComboBox Data="@Items"
@bind-Value="@Value"
CssClass="cw-480" >
<EditBoxDisplayTemplate>
@GetTemplateContent(context.DataItem)
</EditBoxDisplayTemplate>
...
</DxComboBox>
@code {
string Value { get; set; } = "Low";
IEnumerable<string> Items = new List<string>() {"Low", "Normal", "High"};
RenderFragment GetTemplateContent(string item) {
return @<div class="template-container">
<svg class="@GetIconCssClass(item)" role="img">
<use href="@GetIconHref(item)"/>
</svg>
@item
</div>;
}
string GetIconHref(string item) {
return item != null ? StaticAssetUtils.GetImagePath($"icons/levels.svg#dx-{item.ToLower()}-level") : string.Empty;
}
string GetIconCssClass(string item) {
var cssClass = "template-icon";
if (item != null)
cssClass += $" {item.ToLower()}-level";
return cssClass;
}
}
class StaticAssetUtils {
static string libraryPath = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
public static string GetContentPath(string assetPath) {
return $"./_content/{libraryPath}/{assetPath}";
}
public static string GetImagePath(string imageFileName) {
return GetContentPath($"images/{imageFileName}");
}
}
.template-container {
display: flex;
align-items: center;
}
.template-icon {
fill: currentColor;
width: 1rem;
height: 1rem;
margin-right: 0.375rem;
}
.low-level {
color: #D73F3F;
}
.high-level {
color: #1B8A10;
}
.normal-level {
color: #406CF4;
}
You can also create an edit box template that supports user input and filter mode:
Add <EditBoxDisplayTemplate>…</EditBoxDisplayTemplate> to the ComboBox markup.
Declare a DxInputBox object within the EditBoxTemplate markup.
Optional. Use the DxComboBox‘s InputCssClass to customize input box appearance.
Optional. Set the DxComboBox.AllowUserInput to true.
Optional. Use the SearchMode property to enable search mode.
Optional. Use the NullText property to display the prompt text in the edit box when the editor’s Value is null.
<DxComboBox Data="@Cities"
@bind-Value="@CurrentCity"
AllowUserInput="true"
SearchMode="ListSearchMode.AutoSearch"
SearchFilterCondition="ListSearchFilterCondition.StartsWith"
NullText="Select City ..."
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto">
<EditBoxDisplayTemplate>
@if (context != null) {
<span class="content">Selected City: </span>
}
<DxInputBox/>
</EditBoxDisplayTemplate>
</DxComboBox>
@code {
string CurrentCity { get; set; } = "London";
IEnumerable<string> Cities = new List<string>() { "New York", "London", "Berlin", "Paris" };
}
.content {
white-space: pre;
}
Run Demo: ComboBox - Edit Box Display Template
Use the following properties to customize cell appearance in a multi-column ComboBox.
| Property | Container | Scope |
|---|---|---|
| ColumnCellDisplayTemplate | DxComboBox | All cells in a ComboBox |
| CellDisplayTemplate | DxListEditorColumn | Cells in the current column |
These properties can be combined within a single ComboBox. If both templates are defined, the column-specific CellDisplayTemplate takes precedence over the global ColumnCellDisplayTemplate for cells in that particular column. This functionality allows you to set a common template for all columns and then override it for individual columns that require different formatting.
The following code snippet customizes the appearance of different columns in a ComboBox control.
<DxComboBox Data="Subscriptions.Plans"
@bind-Value="SelectedPlan"
EditFormat="{0}">
<Columns>
<DxListEditorColumn FieldName="Name" Caption="Plan">
<CellDisplayTemplate>
<div class="text-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 class="text-right">
@($"{context.Value:C}")
</div>
</ColumnCellDisplayTemplate>
</DxComboBox>
@code {
SubscriptionPlan SelectedPlan { get; set; }
}
public class SubscriptionPlan(
int id,
string name,
int priceMonth,
int priceQuarter,
int priceYear
)
{
public int Id { get; set; } = id;
public string Name { get; set; } = name;
public int PriceMonth { get; set; } = priceMonth;
public int PriceQuarter { get; set; } = priceQuarter;
public int PriceYear { get; set; } = priceYear;
}
public static class Subscriptions
{
public static List<SubscriptionPlan> Plans { get; } = [
new SubscriptionPlan(1, "Basic", 10, 25, 90),
new SubscriptionPlan(2, "Standard", 20, 50, 180),
new SubscriptionPlan(3, "Premium", 30, 75, 270),
new SubscriptionPlan(4, "Enterprise", 50, 125, 450)
];
}
.text-right {
text-align: right;
}
.text-left {
text-align: left;
}
Run Demo: ComboBox - Cell Display Template
The ComboBox displays an empty data area in the following cases:
Use the EmptyDataAreaTemplate to customize content displayed in this empty region. The template’s context parameter includes the IsDataLoading property that allows you to determine whether the ComboBox is still loading data.
@inject NwindDataService NwindDataService
<DxComboBox Data="@DataItems"
@bind-Value="@Item"
CssClass="cw-480"
NullText="Select an order..."
>
<EmptyDataAreaTemplate>
@if (!context.IsDataLoading) {
<div class="empty-data-area-template">
<div class="d-flex flex-column">
No orders found
</div>
</div>
}
</EmptyDataAreaTemplate>
</DxComboBox>
@code {
IEnumerable<string> DataItems { get; set; }
string Item { get; set; }
}
.empty-data-area-template {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 150px;
padding: 2rem 0;
}
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public partial class Employee {
public Employee() {
this.Orders = new List<Order>();
}
public int EmployeeId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string Title { get; set; }
public string TitleOfCourtesy { get; set; }
public Nullable BirthDate { get; set; }
public Nullable HireDate { 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 HomePhone { get; set; }
public string Extension { get; set; }
public byte[] Photo { get; set; }
public string Notes { get; set; }
public Nullable<int> ReportsTo { get; set; }
public string PhotoPath { get; set; }
public string GroupName { get; set; }
public virtual ICollection<Order> Orders { get; set; }
public string Text => $"{FirstName} {LastName} ({Title})";
public string FullName => $"{FirstName} {LastName}";
public string ImageFileName => $"employees/{EmployeeId}.jpg";
}
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<Employee>> GetEmployeesAsync(CancellationToken ct = default) {
// Return your data here
}
}
}
public class Startup {
public void ConfigureServices(IServiceCollection services) {
// ...
services.AddScoped<NwindDataService>();
}
}