Binding Custom Classes to MudTreeView

Binding Custom Classes to MudTreeView

The example provided in the documentation is based on a string type, combined with a custom "presenter" which is used to display the values.

Strings can be a little different; they're often used as default values with special behavior, particularly in user interface scenarios.

However, buried deep in the repository was this example.

I'm including it below as I don't want the snippet to vanish.

<h3>MyTreeView</h3>
<MudTextField @bind-Value="SearchValue" Label="Search" Variant="Variant.Text" Immediate="true" ></MudTextField>


<MudPaper Width="300px" Elevation="0">
    <MudTreeView T="Animal" Items="TreeItems" SelectionMode="SelectionMode.MultiSelection" @bind-SelectedValues="SelectedValues">
        <ItemTemplate>
            <MudTreeViewItem @bind-Expanded="@context.Expanded" Items="@GetChildren(context)" Text="@context.Value?.Name" Value="@context.Value"/>
        </ItemTemplate>
    </MudTreeView>
</MudPaper>
@code {

    public string SearchValue { get; set; }
    public IReadOnlyCollection<Animal> SelectedValues { get; set; }

    public List<TreeItemData<Animal>> TreeItems { get; set; } = new();

    public IReadOnlyCollection<TreeItemData<Animal>> GetChildren(TreeItemData<Animal> context) {
        if (context.Children == null)
            return null;
        return context.Children.Where(item=>IsItemVisible(item, SearchValue)).ToArray();
    }

    public bool IsItemVisible(TreeItemData<Animal> item, string searchValue)
    {
        if (string.IsNullOrWhiteSpace(searchValue))
            return true;
        // Value could not be null, because of the constructor
        if (item.Value is null)
        {
            return false;
        }

        return item.Value.Name.Contains(searchValue, StringComparison.InvariantCultureIgnoreCase);
    }

    public class Animal
    {
        public string Name { get; set; }

        public Animal(string name)
        {
            Name = name;
        }
    }

    protected override void OnInitialized()
    {
        TreeItems.Add(new TreeItemData<Animal> { Value=new Animal("All Mail") });
        TreeItems.Add(new TreeItemData<Animal> { Value=new Animal("Trash") });
        TreeItems.Add(new TreeItemData<Animal> { Value=new Animal("Categories"),        
            Expanded = true,
            Children =
            [
                new TreeItemData<Animal> { Value=new Animal("Social") },
                new TreeItemData<Animal> { Value=new Animal("Updates") },
                new TreeItemData<Animal> { Value=new Animal("Forums") },
                new TreeItemData<Animal> { Value=new Animal("Promotions") },
            ]
        });
    }
}

The key part of this is that it uses T="Animal" in the definition and the entire thing binds to a List<TreeItemData<Animal>>.

It's their TreeItemData<T> that allows for nested children, and it's required to use it for the control to work.

In this example, they're adding a search function which is just a bonus.

The GetChildren method is also key. I had the usual problems with nullability and that fixed it.

Good luck.