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.