Skip to content

excubo-ag/Blazor.TreeViews

Repository files navigation

Excubo.Blazor.TreeViews

Nuget Nuget GitHub

Excubo.Blazor.TreeViews is a native-Blazor tree-view component.

Demo on github.io using Blazor Webassembly

How to use

1. Install the nuget package Excubo.Blazor.TreeViews

Excubo.Blazor.TreeViews is distributed via nuget.org. Nuget

Package Manager:

Install-Package Excubo.Blazor.TreeViews

.NET Cli:

dotnet add package Excubo.Blazor.TreeViews

Package Reference

<PackageReference Include="Excubo.Blazor.TreeViews" />

2. Add the TreeView component to your app

@using Excubo.Blazor.TreeViews

<TreeView Items="Items" />

Have a look at the fully working examples provided in the sample project.

Design principles

  • Blazor API

The API should feel like you're using Blazor, not a javascript library.

  • Minimal js, minimal css, lazy-loaded only when you use the component

The non-C# part of the code of the library should be as tiny as possible. We set ourselves a maximum amount of 10kB for combined js+css. The current payload is 0kB.

Breaking changes

Version 4.X.Y

Starting with version 4.0.0, programmatic changes of selected items was improved. Previously, one had to add @key=version to the TreeView and increment the version after each update. However, this was the cause for a bug. The new design requires the user to take an element reference to the TreeView (@ref=tree_view) and call tree_view.RefreshSelection() after selection has been modified. See TestProject_Components/Pages/Selection.razor for an example.

Version 3.X.Y

Starting with version 3.0.0, only the net6.0 TFM is targeted. This is a change to simplify dependency management and we strongly encourage all users to upgrade to net6.0.

Version 2.X.Y

In this version, @qinhuaihe added support for Disabled, both on individual elements, and the entire tree view. This required a few changes to the API, including how custom checkbox styles are handled. Please refer to the section below to learn how to implement a custom checkbox style.

Checkbox style from another component library

It is possible to configure the checkbox style for a TreeView with AllowSelection enabled. Use the CheckboxTemplate parameter:

<TreeView Items="Items" AllowSelection="true" CheckboxTemplate="checkbox_template" />

Because of a quirk in Blazor, writing the correct code for the CheckboxTemplate can be quite tricky. See below for a list of snippets of correct checkboxes in some of the common component libraries. If you can't find your favorite library, please consider contributing to this list.

@code {
    private static readonly object no_render = new object();
    private static readonly CheckboxFragment checkbox_template_matblazor =
        (value, indeterminate, value_changed, disabled) =>
            (builder) =>
            {
                builder.OpenComponent<MatBlazor.MatCheckbox<bool?>>(0);
                builder.AddAttribute(1, nameof(MatBlazor.MatCheckbox<bool?>.Value), indeterminate ? null : value);
                builder.AddAttribute(2, nameof(MatBlazor.MatCheckbox<bool?>.ValueChanged), EventCallback.Factory.Create<bool?>(no_render, (v) => { if (v != null) { value_changed(v.Value); } }));
                builder.AddAttribute(3, nameof(MatBlazor.MatCheckbox<bool?>.Indeterminate), true);
                builder.AddAttribute(4, nameof(MatBlazor.MatCheckbox<bool?>.Disabled), disabled);
                builder.AddEventStopPropagationAttribute(5, "onclick", true);
                builder.CloseComponent();
            };
}
@code {
    private static readonly object no_render = new object();
    private static readonly CheckboxFragment checkbox_template_material_blazor =
        (value, indeterminate, value_changed, disabled) =>
            (builder) =>
            {
                builder.OpenComponent<Material.Blazor.MBCheckbox>(0);
                builder.AddAttribute(1, nameof(Material.Blazor.MBCheckbox.Value), value);
                builder.AddAttribute(2, nameof(Material.Blazor.MBCheckbox.ValueChanged), EventCallback.Factory.Create<bool>(no_render, value_changed));
                builder.AddAttribute(3, nameof(Material.Blazor.MBCheckbox.IsIndeterminate), indeterminate);
                builder.AddAttribute(4, nameof(Material.Blazor.MBCheckbox.Disabled), disabled);
                builder.AddEventStopPropagationAttribute(5, "onclick", true);
                builder.CloseComponent();
            };
}
@code {
    private static readonly object no_render = new object();
    private static readonly CheckboxFragment checkbox_template_radzen =
        (value, indeterminate, value_changed, disabled) =>
            (builder) =>
            {
                builder.OpenComponent<Radzen.Blazor.RadzenCheckBox<bool?>>(0);
                builder.AddAttribute(1, nameof(Radzen.Blazor.RadzenCheckBox<bool?>.Value), indeterminate ? null : value);
                builder.AddAttribute(2, nameof(Radzen.Blazor.RadzenCheckBox<bool?>.ValueChanged), EventCallback.Factory.Create<bool?>(no_render, (v) => { if (v != null) { value_changed(v.Value); } }));
                builder.AddAttribute(3, nameof(Radzen.Blazor.RadzenCheckBox<bool?>.TriState), false);
                builder.AddAttribute(4, nameof(Radzen.Blazor.RadzenCheckBox<bool?>.Disabled), disabled);
                builder.AddEventStopPropagationAttribute(5, "onclick", true);
                builder.CloseComponent();
            };
}

Samples and Tutorials

The official usage examples can be found on https://excubo-ag.github.io/Blazor.TreeViews/.

All following links provided here are not affiliated with excubo ag and have been contributed by the community.