DxTreeView Class
A navigation control that displays items as a tree.
Namespace: DevExpress.Blazor
Assembly: DevExpress.Blazor.v23.2.dll
NuGet Package: DevExpress.Blazor
Declaration
public class DxTreeView :
DxNavigationControlComponent<TreeViewJSInteropProxy, ITreeViewModel>,
ITreeViewJSInteropProxyServer,
IJSCallback,
ISizeModeAccessor,
IRequireSelfCascading,
ICascadingSizeModeProvider
Remarks
The DevExpress TreeView component for Blazor (<DxTreeView>
) displays hierarchical data structures within a tree-like UI. The component implements navigation within a web application.
Add a TreeView to a Project
Follow the steps below to add the TreeView component to an application:
- 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.
- Add the
<DxTreeView>
…</DxTreeView>
markup to a.razor
file. - Configure the component: add nodes or bind the TreeView to data, handle expand/collapse events, enable node selection, and so on (see the sections below).
Add Nodes (Unbound Mode)
In unbound mode, you should create a node hierarchy in the markup. A DxTreeViewNode class instance implements a node. The DxTreeView.Nodes collection declares root nodes. Each node can have its own collection of child nodes – DxTreeViewNode.Nodes.
For each node, you can specify the following settings:
- Name
- Specifies the unique identifier name for the current node.
- Text
- Specifies the node text content.
- IconCssClass
- Specifies the CSS class of the icon displayed by the node.
- NavigateUrl
- Specifies the navigation location for the node.
<DxTreeView>
<Nodes>
<DxTreeViewNode Name="Overview" Text="Overview" NavigateUrl="https://demos.devexpress.com/blazor/" />
<DxTreeViewNode Name="Editors" Text="Data Editors" Expanded="true">
<Nodes>
<DxTreeViewNode Text="Combobox" NavigateUrl="https://demos.devexpress.com/blazor/ComboBox" />
<DxTreeViewNode Text="Spin Edit" NavigateUrl="https://demos.devexpress.com/blazor/SpinEdit" />
</Nodes>
</DxTreeViewNode>
<DxTreeViewNode Name="FormLayout" Text="Form Layout" NavigateUrl="https://demos.devexpress.com/blazor/FormLayout" BadgeText="Upd" />
<DxTreeViewNode Name="TreeView" Text="TreeView" NavigateUrl="https://demos.devexpress.com/blazor/TreeView" BadgeText="New" />
<DxTreeViewNode Name="Tabs" Text="Tabs" NavigateUrl="https://demos.devexpress.com/blazor/Tabs" Visible="false" BadgeText="New" />
</Nodes>
</DxTreeView>
Bind to Data (Bound Mode)
You can populate the TreeView component with items from a data source.
Follow the steps below to bind TreeView to data:
Use the Data property to specify a data source. You can use different collection types:
- Flat data (a collection of items organized as a single-level structure)
- Hierarchical data (a collection of nested nodes)
Add the DataMappings tag to the component’s markup.
Create the DxTreeViewDataMapping instance and map node properties (HasChildren, IconCssClass, and so on) to data source fields. Mappings are used to assign data from the source collection to the component’s data model.
For flat data collections, use the Key and ParentKey properties to create a hierarchy of items. If the TreeView’s structure is linear, you can omit these properties.
For hierarchical data collections, the Children property is required to build the data model.
You can create multiple
DxTreeViewDataMapping
instances to specify different mappings for different nesting levels. Use the Level property to specify the node level for which data mappings are applied.
Flat Data
The code below binds TreeView to a collection of flat data items. It specifies mappings for Text, Key, and ParentKey properties.
@if(Data == null) {
<p><em>Loading...</em></p>
} else {
<div class="cw-320">
<DxTreeView Data="@Data"
@* ... *@
AnimationType="LayoutAnimationType.Slide">
<DataMappings>
<DxTreeViewDataMapping Text="Name"
Key="Id"
ParentKey="CategoryId"/>
</DataMappings>
</DxTreeView>
</div>
}
@code {
List<FlatDataItem> Data { get; set; }
protected override void OnInitialized() {
IEnumerable<ProductFlat> products = ProductData.Products;
IEnumerable<ProductCategory> productSubcategories = ProductData.Categories;
Data = new List<FlatDataItem>(Enum.GetValues<ProductCategoryMain>().Select(i => new FlatDataItem() { Name = i.ToString(), Id = i }));
Data.AddRange(products.Select(i => new FlatDataItem() { Name = i.ProductName, Id = i.Id, CategoryId = i.ProductCategoryId }));
Data.AddRange(productSubcategories.Select(i => new FlatDataItem() { Name = i.Subcategory, Id = i.SubcategoryID, CategoryId = i.Category }));
}
}
Hierarchical Data
The code below binds TreeView to a collection of ChemicalElementGroup
objects. The code specifies Children and Text mappings to adjust the TreeView data model to the specified data source.
<DxTreeView Data="@ChemicalElements.Groups"
@* ... *@
AnimationType="LayoutAnimationType.Slide">
<DataMappings>
<DxTreeViewDataMapping Children="Groups"
Text="Name"/>
</DataMappings>
</DxTreeView>
Load Child Nodes on Demand
When the LoadChildNodesOnDemand option is set to true
, the component does not load child nodes until the parent node is expanded for the first time. Use this option to optimize the component’s performance when it is bound to a large data source.
You can load child nodes on demand in either bound or unbound mode. Note that bound mode works with hierarchical structures only and requires the HasChildren property. The component uses this property to determine how to render nodes before they are expanded for the first time (for example, whether expand buttons should appear).
<DxTreeView @ref="@treeView"
CssClass="cw-480"
Data="@DataSource"
LoadChildNodesOnDemand="true"
@* ... *@
AnimationType="LayoutAnimationType.Slide">
<DataMappings>
<DxTreeViewDataMapping HasChildren="@(nameof(DateTimeGroup.HasSubGroups))"
Children="@(nameof(DateTimeGroup.SubGroups))"
Text="@(nameof(DateTimeGroup.Title))"/>
</DataMappings>
</DxTreeView>
@code {
DxTreeView treeView;
IEnumerable<DateTimeGroup> DataSource = new List<DateTimeGroup>() {
new DateTimeGroup(new DateTime(DateTime.Now.Year, 1, 1), DateTimeGroupType.Year)
};
protected override void OnAfterRender(bool firstRender) {
if(firstRender) {
var todayDate = DateTime.Now;
treeView.SetNodeExpanded(n => n.Text == todayDate.Year.ToString(), true);
}
base.OnAfterRender(firstRender);
}
}
Refer to the following section for information about limitations: Load Child Nodes on Demand - Limitations.
Expand and Collapse Nodes
To expand or collapse a node, users can click or double-click it or click its expand button.
The example below shows a TreeView with custom Expand buttons.
The table below lists related API members:
Member | Description |
---|---|
Specifies user actions that expand or collapse a node. | |
Specifies whether expand buttons are visible. | |
Expands or collapses the specified node. | |
Returns whether the specified node is expanded. | |
Expands the nodes down to the specified node. | |
Expands all nodes in the DxTreeView. | |
Collapses all nodes in the DxTreeView. | |
Specify a CSS class for the expand button’s icon. | |
Specify a CSS class for the collapse button’s icon. |
The following events fire when the state of a node changes:
Member | Description |
---|---|
Fires when a node is about to be expanded and allows you to cancel the action. | |
Fires when a node is about to be collapsed and allows you to cancel the action. | |
Fires after a node has been expanded. | |
Fires after a node has been collapsed. | |
Fires when a TreeView’s node expands or collapses. |
Filter Nodes
Enable the ShowFilterPanel option to activate the filter panel. If a user types in a search string, the component displays matching nodes, and optionally, their parent/child nodes. Note that if you activate the filter option with the enabled LoadChildNodesOnDemand option, the component loads all its nodes into memory.
<DxTreeView ShowFilterPanel="true">
@* ... *@
</DxTreeView>
Use the FilterMode property to specify how the component displays the filter operation results. The following options are available:
- EntireBranch
- The component displays a node that meets the filter criteria and all its parent and child nodes, even if they do not meet the criteria.
- ParentBranch
- The component displays a node that meets the filter criteria and all its parent nodes, even if they do not meet the criteria.
- Nodes
- The component displays only nodes that meet the filter criteria. A node at the hierarchy’s highest level that meets the filter criteria becomes the root node. The node’s child nodes that meet the filter criteria move to the upper hierarchy levels.
The table below lists available API members:
Member | Description |
---|---|
Specifies the minimum number of characters a user must type in the search box to apply the filter. | |
Allows you to implement custom filter logic. | |
Specifies the filter criteria used to filter the component’s nodes. |
Select Nodes
Set the AllowSelectNodes property to true
to enable node selection. Once a user clicks a node, it is highlighted and the SelectionChanged event is raised. The following example demonstrates how to handle this event to expand the selected node (if it has children) and to collapse other nodes:
<DxTreeView @ref="@treeView" AllowSelectNodes="true" SelectionChanged="@SelectionChanged">
...
</DxTreeView>
@code {
DxTreeView treeView;
protected void SelectionChanged(TreeViewNodeEventArgs e) {
treeView.CollapseAll();
treeView.ExpandToNode((n) => n.Text == e.NodeInfo.Text);
if (!e.NodeInfo.IsLeaf) {
treeView.SetNodeExpanded((n) => n.Text == e.NodeInfo.Text, true);
}
}
}
Refer to the list below for other related API members:
- AllowSelection
- Specifies whether the TreeView node can be selected.
- GetSelectedNodeInfo()
- Returns information about the selected node.
- SelectNode(Func<ITreeViewNodeInfo, Boolean>)
- Selects the specified node.
- ClearSelection()
- Clears node selection.
Check Nodes
Set the CheckMode property to Multiple
or Recursive
to display checkboxes in nodes. The CheckedChanged event is raised when a user changes a node’s check state.
The NavigationCheckedChangedEventArgs<TInfo> class contains the following collections:
- CheckedItems
- Returns all checked items.
- LastCheckedItems
- Returns items checked during the last operation.
- LastUncheckedItems
- Returns items unchecked during the last operation.
The example below handles the CheckedChanged
event to respond to user interactions with node checkboxes. The handler obtains the collection of nodes whose state is checked. If the collection is not empty, the code displays the first node’s text.
First checked node: @FirstChecked
<DxTreeView Data="@Data"
CheckMode="TreeViewCheckMode.Recursive"
CheckedChanged="CheckedChanged">
<DataMappings>
<DxTreeViewDataMapping Text="Name"
Key="Id"
ParentKey="CategoryId" />
</DataMappings>
</DxTreeView>
@code {
string? FirstChecked = "none";
void CheckedChanged(TreeViewCheckedChangedEventArgs e) {
var firstCheckedNode = e.CheckedItems.FirstOrDefault();
FirstChecked = firstCheckedNode != null ? firstCheckedNode.Text : "none";
}
}
Set the DxTreeViewNode.AllowCheck property to false
to prevent users from checking a specific node.
Note
The following actions change the check state of all nodes, even those that do not meet the applied filter criteria
:
- CheckAll() method call
- ClearCheck() method call
- Recursive check mode update
Refer to the list below for other related API members:
- Checked
- Specifies whether the node is checked.
- CheckAll()
- Checks all nodes in the TreeView.
- CheckAllVisible
- Specifies whether the Check All box is visible.
- CheckAllText
- Specifies the label of the Check All box.
- ClearCheck()
- Unchecks all nodes.
- CheckNodeByClick
- Specifies whether users can click nodes to check and uncheck them.
Organize Navigation Within the Application
Use the NavigateUrl property to specify a URL where the client web browser navigates when a node is clicked. The DxTreeView.Target property specifies the common target attribute’s value for all nodes in the TreeView. To override the attribute value for a specific node, use the DxTreeViewNode.Target property.
The code below sets the common target
attribute’s value for all nodes to _blank
and overrides this value for the first node (sets it to _self
explicitly).
<DxTreeView Target="_blank">
<Nodes>
<DxTreeViewNode Name="Overview"
Text="Overview"
NavigateUrl="https://demos.devexpress.com/blazor/"
Target="_self"/>
<DxTreeViewNode Name="Editors" Text="Data Editors" Expanded="true">
<Nodes>
<DxTreeViewNode Text="Combobox" NavigateUrl="https://demos.devexpress.com/blazor/ComboBox" />
<DxTreeViewNode Text="Spin Edit" NavigateUrl="https://demos.devexpress.com/blazor/SpinEdit" />
</Nodes>
</DxTreeViewNode>
</Nodes>
</DxTreeView>
The item becomes selected if its DxTreeViewNode.NavigateUrl property value matches the active web page. If the control does select the item, it expands all parent items. Set the AllowSelectNodes property value to true
to enable this functionality.
The following example disables URL synchronization:
<DxTreeView AllowSelectNodes="true" UrlMatchMode="NavigationUrlMatchMode.None">
<Nodes>
<DxTreeViewNode NavigateUrl="./" Text="Overview"></DxTreeViewNode>
<DxTreeViewNode NavigateUrl="grid" Text="Grid"></DxTreeViewNode>
</Nodes>
</DxTreeView>
Apply Customizations
Disable User Interactions
Set the Enabled property to false
to ignore user interactions.
<button type="button" @onclick="@(() => ToggleTreeViewEnabled())">Enable/Disable TreeView</button>
<DxTreeView Enabled="@TreeViewEnabled">
<Nodes>
<DxTreeViewNode Text="Metals">
<Nodes>
<DxTreeViewNode Text="Alkali metals" />
<DxTreeViewNode Text="Inner transition elements">
<Nodes>
<DxTreeViewNode Text="Lanthanides" />
<DxTreeViewNode Text="Actinides" />
</Nodes>
</DxTreeViewNode>
</Nodes>
</DxTreeViewNode>
</Nodes>
</DxTreeView>
@code {
bool TreeViewEnabled { get; set; } = false;
void ToggleTreeViewEnabled() { TreeViewEnabled = !TreeViewEnabled; }
}
Add a Vertical scrollbar
The TreeView component automatically displays a vertical scrollbar when its nodes do not fit the viewport:
<style>
.my-treeview {
height: 180px;
}
</style>
<div>
<DxTreeView CssClass="my-treeview">
<Nodes>
<DxTreeViewNode Text="Data Editors" />
<DxTreeViewNode Text="Data Grid">
<Nodes>
<DxTreeViewNode Text="Editing" />
<DxTreeViewNode Text="Sorting" />
<DxTreeViewNode Text="Export" />
</Nodes>
</DxTreeViewNode>
<DxTreeViewNode Text="Rich Text Editor" />
<DxTreeViewNode Text="Scheduler" />
<DxTreeViewNode Text="Navigation" />
</Nodes>
</DxTreeView>
</div>
Wrap Node Text
If a Text value does not fit into a node as a single line, the node displays multiple lines of text. Set the TextWrapEnabled
property to false
to disable word wrap and trim extra words:
<div class="container">
<DxTreeView TextWrapEnabled="false">
<Nodes>
<DxTreeViewNode Text="Data Binding">
<Nodes>
<DxTreeViewNode Text="Large Data (Instant Feedback Source)" />
<DxTreeViewNode Text="Large Data (Queryable)" />
<DxTreeViewNode Text="Unbound Columns" />
</Nodes>
</DxTreeViewNode>
</Nodes>
</DxTreeView>
</div>
Templates
Use the following <DxTreeView>
properties to specify a common node template and a text template for all nodes:
In unbound mode, you can create node templates individually. These templates have priority over common templates. Use the following <DxTreeViewNode>
properties:
<DxTreeView Data="@ComponentSets.Data"
@ref="@treeView">
<DataMappings>
<DxTreeViewDataMapping Children="ComponentSets" />
</DataMappings>
<NodeTemplate>
@{
var dataItem = (ComponentSet)context.DataItem;
}
@if (!context.IsLeaf) {
<h4 class="my-0 p-2 d-flex align-items-center">
@if (context.Expanded) {
<span class="oi oi-chevron-top"></span>
}
else {
<span class="oi oi-chevron-bottom"></span>
}
<span class="ms-3 flex-grow-1">@dataItem.Title</span>
</h4>
}
else {
<div class="d-flex p-2">
<div class="flex-grow-1">
<h5 class="mt-0">@dataItem.Title</h5>
@dataItem.Description
</div>
</div>
}
</NodeTemplate>
</DxTreeView>
@code {
DxTreeView treeView;
protected override Task OnAfterRenderAsync(bool firstRender) {
if(firstRender)
treeView.ExpandAll();
return base.OnAfterRenderAsync(firstRender);
}
}
Troubleshooting
If a Blazor application throws unexpected exceptions, refer to the following help topic: Troubleshooting.