I'm developing an application on Win UI and I need to make a TreeView with different parent and child nodes. The parent nodes are objects of the "Silos" class.
public class Silos : BindableBase
{
private ObservableCollection<Wire> wiresObservable;
public ObservableCollection<Wire> WiresObservable
{
get => wiresObservable; set=>SetProperty(ref this.wiresObservable, value);
}
}
Each "Silos" object has child "Wire" objects.
public class Wire : BindableBase
{
private int id; // уникальный идентификатор подвески
private int number;
}
I am able to output a list of Silos, but it does not output Wire objects. How do I do this?
The code that outputs the Silos list.
<TreeView x:Name="TreeSilos" SelectionMode="Multiple" ItemsSource="{x:Bind ViewModel.Siloses}">
<TreeView.ItemTemplate>
<DataTemplate x:DataType="local:Silos">
<TreeViewItem ItemsSource="{x:Bind Wires, Mode=OneWay}" Content="{x:Bind Name}" >
</TreeViewItem>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
I looked at the examples on the Microsoft website. https://learn.microsoft.com/ru-ru/windows/apps/design/controls/tree-view
You can create a custom DataTemplateSelector and select a DataTemplate
for each type.
Let me show you an example for a Parent type and a Child type:
Parent.cs
public partial class Parent(string name) : ObservableObject
{
[ObservableProperty]
private string _name = name;
[ObservableProperty]
private ObservableCollection<Child> _children = [];
}
Child.cs
public partial class Child(string name) : ObservableObject
{
[ObservableProperty]
private string _name = name;
}
TreeViewItemTemplateSelector.cs
public class TreeViewItemTemplateSelector : DataTemplateSelector
{
public DataTemplate ParentItemTemplate { get; set; } = new();
public DataTemplate ChildItemTemplate { get; set; } = new();
protected override DataTemplate SelectTemplateCore(object item)
{
return item switch
{
Parent => ParentItemTemplate,
Child => ChildItemTemplate,
_ => base.SelectTemplateCore(item)
};
}
}
ShellViewModel.cs
public partial class ShellViewModel : ObservableObject
{
[ObservableProperty]
private ObservableCollection<Parent> _parents = [];
public ShellViewModel()
{
var parent1 = new Parent("Parent 1");
parent1.Children.Add(new Child("Child 1"));
var parent2 = new Parent("Parent 2");
parent2.Children.Add(new Child("Child 1"));
parent2.Children.Add(new Child("Child 2"));
var parent3 = new Parent("Parent 3");
parent3.Children.Add(new Child("Child 1"));
parent3.Children.Add(new Child("Child 2"));
parent3.Children.Add(new Child("Child 3"));
Parents.Add(parent1);
Parents.Add(parent2);
Parents.Add(parent3);
}
}
Shell.xaml.cs
public sealed partial class Shell : Page
{
public Shell()
{
InitializeComponent();
}
public ShellViewModel ViewModel { get; } = new();
}
Shell.xaml
<Page
x:Class="WinUIDemoApp.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:WinUIDemoApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Page.Resources>
<local:TreeViewItemTemplateSelector x:Name="TreeViewItemTemplateSelector">
<local:TreeViewItemTemplateSelector.ParentItemTemplate>
<DataTemplate x:DataType="local:Parent">
<TreeViewItem
Content="{x:Bind Name}"
ItemsSource="{x:Bind Children}" />
</DataTemplate>
</local:TreeViewItemTemplateSelector.ParentItemTemplate>
<local:TreeViewItemTemplateSelector.ChildItemTemplate>
<DataTemplate x:DataType="local:Child">
<TreeViewItem Content="{x:Bind Name}" />
</DataTemplate>
</local:TreeViewItemTemplateSelector.ChildItemTemplate>
</local:TreeViewItemTemplateSelector>
</Page.Resources>
<TreeView
ItemTemplateSelector="{StaticResource TreeViewItemTemplateSelector}"
ItemsSource="{x:Bind ViewModel.Parents, Mode=OneWay}" />
</Page>
BTW, ObservableObject and ObservableProperty come from the CommunityToolkit.Mvvm NuGet package.