Skip to main content

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.

Blazor Navigation Landing TreeView

Run Demo: TreeView

Add a TreeView to a Project

Follow the steps below to add the TreeView 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 <DxTreeView></DxTreeView> markup to a .razor file.
  3. 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>

TreeView Nodes

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:

  1. 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)
  2. Add the DataMappings tag to the component’s markup.

  3. 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 }));
    }

}

Bind Treview to Flat Data

Run Demo: TreeView - Binding to Flat Data

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>

Bind Treview to Hierarchical Data

Run Demo: TreeView - Binding to Hierarchical Data Watch Video: Data Binding in Navigation Components

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.

Run Demo: TreeView - Load Child Nodes on Demand Mode

View Example: TreeView for Blazor - How to load child nodes on demand (lazy loading)

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.

TreeView Expand Button

The table below lists related API members:

Member

Description

NodeExpandCollapseAction

Specifies user actions that expand or collapse a node.

ShowExpandButtons

Specifies whether expand buttons are visible.

SetNodeExpanded(Func<ITreeViewNodeInfo, Boolean>, Boolean)

Expands or collapses the specified node.

GetNodeExpanded(Func<ITreeViewNodeInfo, Boolean>)

Returns whether the specified node is expanded.

ExpandToNode(Func<ITreeViewNodeInfo, Boolean>)

Expands the nodes down to the specified node.

ExpandAll()

Expands all nodes in the DxTreeView.

CollapseAll()

Collapses all nodes in the DxTreeView.

ExpandButtonIconCssClass

Specify a CSS class for the expand button’s icon.

CollapseButtonIconCssClass

Specify a CSS class for the collapse button’s icon.

The following events fire when the state of a node changes:

Member

Description

BeforeExpand

Fires when a node is about to be expanded and allows you to cancel the action.

BeforeCollapse

Fires when a node is about to be collapsed and allows you to cancel the action.

AfterExpand

Fires after a node has been expanded.

AfterCollapse

Fires after a node has been collapsed.

ExpandedChanged

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>

Filter

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

FilterMinLength

Specifies the minimum number of characters a user must type in the search box to apply the filter.

CustomFilter

Allows you to implement custom filter logic.

FilterString

Specifies the filter criteria used to filter the component’s nodes.

View Example: Implement Custom Filter

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);
        }    
    }
}

Run Demo: TreeView - Node Selection

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.

Run Demo: Checking Multiple Nodes Run Demo: Recursive Node Check Marks

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";
    }
}

Handle checking changes

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:

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>

Disable URL synchronization

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>

Vertical scrolling

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>

Trim node text

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);
    }
}

TreeView Templates

Run Demo: TreeView - Templates

Troubleshooting

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

Inheritance

Object
ComponentBase
DevExpress.Blazor.Base.DxAsyncDisposableComponent
DevExpress.Blazor.Base.DxDecoratedComponent
DxComponentBase
DxComponentBase<DevExpress.Blazor.Internal.JSInterop.TreeViewJSInteropProxy>
DxControlComponent<DevExpress.Blazor.Internal.JSInterop.TreeViewJSInteropProxy>
DxNavigationControlComponent<DevExpress.Blazor.Internal.JSInterop.TreeViewJSInteropProxy, DevExpress.Blazor.Navigation.Internal.ITreeViewModel>
DxTreeView
See Also