Tree

This guide demonstrates how to use the Radzen Blazor Tree component.

Properties

Name Type Default Description
Data IEnumerable null Used during data-binding to populate the tree items.
<RadzenTree Data="@categories">
</RadzenTree>

Events

Name Argument Type Description
Change TreeEventArgs Fired when the user selects a tree item.
Expand TreeExpandEventArgs Fired when the user expands a tree item.
<RadzenTree Change="@OnChange" Expand="@OnExpand">
</RadzenTree>
@code {
  void OnChange(TreeEventArgs args)
  {
  }

  void OnExpand(TreeExpandEventArgs args)
  {
  }
}

TreeEventArgs properties

Name Type Default Description
Text string string.Empty The Text of the tree item that triggered the event.
Value object null The Value of the tree item that triggered the event.

TreeExpandEventArgs properties

Name Type Description
Text string The Text of the tree item that triggered the event.
Value object The Value of the tree item that triggered the event.
Children TreeItemSettings Various settings that control how the children of the tree item are populated.

TreeItemSettings properties

Name Type Default Description
Text Func<object, string> null A function that returns the text of child items depending on the data.
TextProperty string null Specifies the name of the property which determines the text of the child items.
Template RenderFragment null Use to customize the display of the item.
HasChildren Func<object, bool> (data) => false Set this property to specify if a child item has children or not.
Data IEnumerable null The data from which children are created. Set this property to provide data for the children of the current tree item.

RadzenTreeItem Properties

Name Type Default Description
Text string string.Empty The text displayed by the tree item.
Value object null The value associated with the tree item.
Expanded bool false Specifies whether the item is expanded or not.

RadzenTreeLevel Properties

Name Type Default Description
Text Func<object, string> null A function that returns the text of child items depending on the data.
TextProperty string null Specifies the name of the property which determines the text of the child items.
HasChildren Func<object, bool> (data) => true Set this property to specify if a child item has children or not.
Template RenderFragment null Use to customize the display of the items created from this level.
ChildrenProperty string null Specifies the name of the property which returns child data. The value returned by that property should be IEnumerable

Inline definition

The most straight forward way to define a RadzenTree is to specify its items. Here is an example:

<RadzenTree>
    <RadzenTreeItem Text="BMW">
        <RadzenTreeItem Text="M3" />
        <RadzenTreeItem Text="M5" />
    </RadzenTreeItem>
    <RadzenTreeItem Text="Audi">
        <RadzenTreeItem Text="RS4" />
        <RadzenTreeItem Text="RS6" />
    </RadzenTreeItem>
    <RadzenTreeItem Text="Mercedes">
        <RadzenTreeItem Text="C63 AMG" />
        <RadzenTreeItem Text="S63 AMG" />
    </RadzenTreeItem>
</RadzenTree>

Data-binding

Often you would like to data-bind the RadzenTree to a collection of items. For example a collection of categories that has related products.

public class Category
{
   public string CategoryName { get; set; }
   public IEnumerable<Product> Products { get; set; }
}

public class Product
{
   public string ProductName { get; set; }
}

In this case you need to set the Data property of the RadzenTree to your collection and add a few RadzenTreeLevels that specify how each level of items should be data-bound.

<RadzenTree Data="@Northwind.Categories.Include(c => c.Products)">
    <RadzenTreeLevel TextProperty="CategoryName" ChildrenProperty="Products" />
    <RadzenTreeLevel TextProperty="ProductName" HasChildren="@((product) => false)" />
</RadzenTree>

The first RadzenTreeLevel says that the first (root) level of items have their Text set to the CategoryName property of the data. They also have children that are data-bound to the Products property.

The second RadzenTreeLevel says that the second level of items have their Text set to the ProductName property of the data. The don’t have children (specified via HasChildren).

Note how this example uses the Include Entity Framework method to load the related products of a category. If this isn’t done the children items won’t populate.

Load on demand

The previous example loads all tree items instantly. Sometimes you would like to have full control over when children data is loaded. In that case you should use the Expand event.

<RadzenTree Data="@Northwind.Categories" Expand="@OnExpand">
    <RadzenTreeLevel TextProperty="CategoryName"/>
</RadzenTree
@code {
    void OnExpand(TreeExpandEventArgs args)
    {
        var category = args.Value as Category;

        args.Children.Data = category.Include(c => c.Products).Products;
        args.Children.TextProperty = "ProductName";
        args.Children.HasChildren = (product) => false;
    }
}

Here we have only one level (for the categories). Children are populated in the OnExpand method that handles the Expand event. To populate items on demand you need to configure the Children property of the args - set Data, TextProperty and HasChildren.

Load mixed data

The examples so far dealt with trees that had the same type of node per level - first level was categories and second level was products.

Here is how to have mixed types of nodes per level - files and directories in this case.

<RadzenTree Data="@entries" Expand="@LoadFiles">
    <RadzenTreeLevel Text="@GetTextForNode" />
</RadzenTree
@code {
    IEnumerable<string> entries = null;

    protected override void OnInitialized()
    {
        entries = Directory.GetDirectories(HostEnvironment.ContentRootPath);
    }

    string GetTextForNode(object data)
    {
        return Path.GetFileName((string)data);
    }

    void LoadFiles(TreeExpandEventArgs args)
    {
        var directory = args.Value as string;

        args.Children.Data = Directory.EnumerateFileSystemEntries(directory);
        args.Children.Text = GetTextForNode;
        args.Children.HasChildren = (path) => Directory.Exists((string)path);
    }
}

Templates

To customize the way a tree item appears (e.g. add icons, images or other custom markup) you can use the Template option.

Templates in inline definition

Here is an example how to define a tree item template using inline definition.

<RadzenTree>
    <RadzenTreeItem Text="BMW">
        <Template>
            <strong>@context.Text</strong>
        </Template>
        <ChildContent>
            <RadzenTreeItem Text="M3" />
            <RadzenTreeItem Text="M5" />
        </ChildContent>
    </RadzenTreeItem>
</RadzenTree>

The context is the current RadzenTreeItem. You can use its properties as you see fit.

Important: Defining children requires a ChildContent element when a template is specified.

Templates in data-binding

The RadzenTreeLevel also supports templates. Here is an example.

<RadzenTree Data="@Northwind.Categories.Include(c => c.Products)">
    <RadzenTreeLevel TextProperty="CategoryName" ChildrenProperty="Products">
        <Template>
            <strong>@(context as Category).CategoryName</strong>
        </Template>
    </RadzenTreeLevel>
    <RadzenTreeLevel TextProperty="ProductName" HasChildren="@((product) => false)" />
</RadzenTree>

Again the current RadzenTreeItem is represented as the context variable. Use the Value property to get the current data item.

Templates in load on demand

One can specify templates even in load on demand scenarios. The template should either be a custom Blazor component, or you should use a

<RadzenTree Data="@entries" Expand="@LoadFiles">
    <RadzenTreeLevel Text="@GetTextForNode" Template="@FileOrFolderTemplate" />
</RadzenTree
@code {
    IEnumerable<string> entries = null;

    protected override void OnInitialized()
    {
        entries = Directory.GetDirectories(HostEnvironment.ContentRootPath);
    }

    string GetTextForNode(object data)
    {
        return Path.GetFileName((string)data);
    }

    RenderFragment<RadzenTreeItem> FileOrFolderTemplate = (context) => builder =>
    {
        string path = context.Value as string;
        bool isDirectory = Directory.Exists(path);

        // Add a RadzenIcon to the template

        builder.OpenComponent<RadzenIcon>(0);
        builder.AddAttribute(1, "Icon", isDirectory ? "folder" : "insert_drive_file");

        // Set some margin if the current data item is a file (!isDirectory)

        if (!isDirectory)
        {
            builder.AddAttribute(2, "Style", "margin-left: 24px");
        }

        builder.CloseComponent();

        // Append the current item text
        builder.AddContent(3, context.Text);
    };

    void LoadFiles(TreeExpandEventArgs args)
    {
        var directory = args.Value as string;

        args.Children.Data = Directory.EnumerateFileSystemEntries(directory);
        args.Children.Text = GetTextForNode;
        args.Children.HasChildren = (path) => Directory.Exists((string)path);

        // Propagate the Template to the children
        args.Children.Template = FileOrFolderTemplate;
    }
}

We are here for you

Making our users happy is always a priority for us.