Home > Software design >  WPF TreeViewItem template (icon text)
WPF TreeViewItem template (icon text)

Time:05-04

I have this TreeView where every item contains an icon a text:

    <TreeView x:Name="myTreeView" Height="153" VerticalAlignment="Top" Width="215">
        <TreeView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Image Source="{Binding IconSource}"/>
                    <TextBlock Text="{Binding Name}"/>
                </StackPanel>
            </DataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>

this is working (showing every item as icon text) if I use this code-behind:

ObservableCollection<NameIconPair> pairs = new ObservableCollection<NameIconPair>();
pairs.Add(new NameIconPair() { Name = "item 1", IconSource = src });
pairs.Add(new NameIconPair() { Name = "item 2", IconSource = src });
pairs.Add(new NameIconPair() { Name = "item 3", IconSource = src });
myTreeView.ItemsSource = pairs;

public class NameIconPair {
    public string Name { get; set; }
    public BitmapSource IconSource { get; set; }
}

but it does not work if instead of creating an observableCollection and using .ItemsSource, I create every TreeViewItem and add it to the TreeView:

   var pair1 = new NameIconPair() { Name = "item 1", IconSource = src };
   var pair2 = new NameIconPair() { Name = "item 2", IconSource = src };
   var pair3 = new NameIconPair() { Name = "item 3", IconSource = src };

   TreeViewItem node1 = new TreeViewItem { Header = pair, IsExpanded = true };
   TreeViewItem node2 = new TreeViewItem { Header = pair, IsExpanded = true };
   TreeViewItem node3 = new TreeViewItem { Header = pair, IsExpanded = true };
   
   node1.Items.Add(node2);
   node1.Items.Add(node3);
   myTreeView.Items.Add(node1);

How can I make this work?

CodePudding user response:

Add a Children property to your NameIconPair class to make it hierarchical:

public class NameIconPair
{
    public string Name { get; set; }
    public BitmapSource IconSource { get; set; }
    public List<NameIconPair> Children { get; } = new List<NameIconPair>();
}

...and replace the DataTemplate with a HierarchicalDataTemplate that binds to the Children property:

<TreeView x:Name="myTreeView" Height="153" VerticalAlignment="Top" Width="215">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
            <StackPanel Orientation="Horizontal">
                <Image Source="{Binding IconSource}"/>
                <TextBlock Text="{Binding Name}"/>
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

You can build your tree without using TreeViewItem elements in the view model:

var pair1 = new NameIconPair() { Name = "item 1", IconSource = src };
var pair2 = new NameIconPair() { Name = "item 2", IconSource = src };
var pair3 = new NameIconPair() { Name = "item 3", IconSource = src };

var node1 = new NameIconPair { Name = "parent" };
node1.Children.Add(pair1);
node1.Children.Add(pair2);
node1.Children.Add(pair3);

myTreeView.Items.Add(node1); // or add to source collection...
  • Related