I made a custom TreeView with multiple columns. Everything worked well until thee are lots of items in the tree.
I tried to enable Virtualization by doing VirtualizingPanel.IsVirtualizing="True"
(Will be VirtualizingStackPanel.IsVirtualizing
if you are < .NET 4.5) but not only it does not speed it up, it actually made the load time even worse.
On a normal TreeView this property does the trick but I can't find a way to get it to work on my custom Tree
TreeViewItem.cs
public class TreeListViewItem : TreeViewItem
{
protected override DependencyObject GetContainerForItemOverride()
{
return new TreeListViewItem();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is TreeListViewItem;
}
}
TreeListView.cs
public class TreeListView : TreeView
{
public GridViewColumnCollection Columns { get; set; }
public TreeListView()
{
Columns = new GridViewColumnCollection();
}
protected override DependencyObject GetContainerForItemOverride()
{
return new TreeListViewItem();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is TreeListViewItem;
}
}
Node.cs
public class Node
{
public string Data { get; set; }
public List<Node> Children { get; set; }
public Node(string data)
{
Data = data;
Children = new List<Node>();
}
}
ViewModel.cs
public class ViewModel
{
public ObservableCollection<Node> Nodes { get; private set; }
public ViewModel()
{
Nodes = new ObservableCollection<Node>();
Node parent = new Node("Parent");
for (int i = 0; i < 5000; i++)
parent.Children.Add(new Node(i.ToString()));
Nodes.Add(parent);
}
}
MainWindow.xaml
<Window x:Class="WPFTest.MainWindow"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFTest"
Title="Test"
mc:Ignorable="d"
Width="200">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Window.Resources>
<Style TargetType="local:TreeListView">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TreeListView">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer VerticalScrollBarVisibility="Disabled">
<DockPanel>
<GridViewHeaderRowPresenter Columns="{Binding Path=Columns, RelativeSource={RelativeSource TemplatedParent}}"
DockPanel.Dock="Top"/>
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
DockPanel.Dock="Bottom">
<ItemsPresenter/>
</ScrollViewer>
</DockPanel>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="local:TreeListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TreeListViewItem">
<StackPanel>
<Border Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<GridViewRowPresenter x:Name="PART_Header"
Content="{TemplateBinding Header}"
Columns="{Binding Path=Columns, RelativeSource={RelativeSource AncestorType={x:Type local:TreeListView}}}" >
</GridViewRowPresenter>
</Border>
<ItemsPresenter x:Name="ItemsHost" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="false">
<Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<local:TreeListView ItemsSource="{Binding Nodes}" VirtualizingPanel.IsVirtualizing="True">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}"/>
</TreeView.ItemTemplate>
<local:TreeListView.Columns>
<GridViewColumn Header="Test" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<DockPanel>
<TextBlock Text="{Binding Data}"/>
</DockPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</local:TreeListView.Columns>
</local:TreeListView>
</Grid>
</Window>
I tried templating the ItemPanel to be VirtualizingStackPanel
and it did not help either.
I strip out the expander part since it is not relevant. You can double click on the parent node to expand the tree and it will take a long time to load the children.