Page 1 of 2

Expanding treeview performent

Posted: 17 May 2017, 06:49
by PhiLong
Is there any way to use the VirtualizingStackPanel in tree view. It take time to expand a node with 1500 children. How can I improve the expanding time for that node?

Thank you

Re: Expanding treeview performent

Posted: 17 May 2017, 07:42
by ai_enabled
From the release notes, only virtualization of ListView and ListBox controls was announced ("Feature UI virtualization implemented and enabled by default for ListView and ListBox controls." v1.2.6f2).
But it works fine for us with regular ItemsControl with the following style:
<Style TargetType="{x:Type ItemsControl}">
    <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True" />
    <Setter Property="VirtualizingPanel.VirtualizationMode" Value="Recycling" />
    <Setter Property="VirtualizingPanel.ScrollUnit" Value="Pixel" />
</Style>
(we're using it to display about 10k log entries and it works instantly, without virtualization it's unusuable)

TreeView is inherited from ItemsControl, so perhaps it will also virtualize if you apply this properties.
Also this answer might be useful - http://stackoverflow.com/a/8183330

Regards!

UPD. Also this answer - http://stackoverflow.com/a/11600489

Re: Expanding treeview performent

Posted: 18 May 2017, 05:28
by PhiLong
Dear ai_enabled,
Thank you for your quick response.

But I have a question. Does the virtualization always enable? I tried to set IsVirtualizing to True or False, but I can't find any different.
<Style TargetType="{x:Type ItemsControl}" BasedOn="{StaticResource NoesisControlStyle}">
        <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True" />
        <Setter Property="VirtualizingPanel.VirtualizationMode" Value="Recycling" />
        <Setter Property="VirtualizingPanel.ScrollUnit" Value="Pixel" />
        <Setter Property="Background" Value="{x:Null}"/>
        <Setter Property="BorderBrush" Value="{x:Null}"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ItemsControl}">
                    <Border
                      Background="{TemplateBinding Background}"
                      BorderBrush="{TemplateBinding BorderBrush}"
                      BorderThickness="{TemplateBinding BorderThickness}"
                      Padding="{TemplateBinding Padding}">
                        <ItemsPresenter />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
<TreeView  ItemsSource="{Binding Root}" x:Name="modelTree" >
	<TreeView.ItemsPanel>
		<ItemsPanelTemplate>
			<VirtualizingStackPanel IsItemsHost="True" />                   
		</ItemsPanelTemplate>
	</TreeView.ItemsPanel>
	<TreeView.ItemContainerStyle>
		<!--Style binds a TreeViewItem to a TreeViewItemViewModel. -->
		<Style TargetType="{x:Type TreeViewItem}">
			<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
			<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
			<Setter Property="FontWeight" Value="Normal" />
			<Style.Triggers>
				<Trigger Property="IsSelected" Value="True">
					<Setter Property="FontWeight" Value="Bold" />
					<Setter Property="local:MainLayout.BringIntoViewWhenSelected" Value="True" />
				</Trigger>
			</Style.Triggers>
		</Style>
	</TreeView.ItemContainerStyle>
	<TreeView.Resources>
		<HierarchicalDataTemplate DataType="{x:Type viewModel:FileNode}" ItemsSource="{Binding Children}">
			<StackPanel Orientation="Horizontal" ContextMenu="{StaticResource TreeViewContextMenuTemplate}">
				<Image Width="16" Height="16" Margin="3,0" Source="../Images/Icons/ic_file_modeltree.png" />
				<TextBlock Text="{Binding Name}" Margin="0,2" />
			</StackPanel>
		</HierarchicalDataTemplate>
		<HierarchicalDataTemplate DataType="{x:Type viewModel:GroupNode}" ItemsSource="{Binding Children}">
			<StackPanel Orientation="Horizontal" ContextMenu="{StaticResource TreeViewContextMenuTemplate}">
				<Image Width="16" Height="16" Margin="3,0" Source="../Images/Icons/ic_group_modeltree.png" />
				<TextBlock Text="{Binding Name}" Margin="0,2" />
			</StackPanel>
		</HierarchicalDataTemplate>
		<HierarchicalDataTemplate DataType="{x:Type viewModel:LeafNode}" ItemsSource="{Binding Children}">
			<StackPanel Orientation="Horizontal" ContextMenu="{StaticResource TreeViewContextMenuTemplate}">
				<Image Width="16" Height="16" Margin="3,0" Source="../Images/Icons/ic_leaf_modeltree.png" />
				<TextBlock Text="{Binding Name}" Margin="0,2" />
			</StackPanel>
		</HierarchicalDataTemplate>
	</TreeView.Resources>
</TreeView>
Did I do something wrong? It took ~4 seconds for expanding the node with ~1500 children.
profiler.png
Thank you

Re: Expanding treeview performent

Posted: 18 May 2017, 07:38
by ai_enabled
@PhiLong,
If I recall correctly IsVirtualizing is enabled by default for ItemsControl and ListBox, but I cannot be sure about TreeView - I've never tried it
So it makes sense to define IsVirtualizing as well.

Are you sure your Style declaration (targeting {x:Type ItemsControl}) is applied to TreeView? I would try changing it to target {x:Type TreeView} to be sure.

Also you can simply add these properties to the <TreeView> declaration.
IsVirtualizing="True"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling"
VirtualizingPanel.ScrollUnit="Pixel"
If it still doesn't virtualize (you see no difference in Unity Profiler) we need to wait for a response from the NoesisGUI team. Perhaps this feature is simply not supported yet for HierarchicalDataTemplate.

Regards!

Re: Expanding treeview performent

Posted: 18 May 2017, 08:30
by PhiLong
I tried to set those value to TreeView property directly, but I still didn't see any effect.

anyway, thank you, ai_enabled!

Re: Expanding treeview performent

Posted: 18 May 2017, 19:28
by sfernandez
To enable virtualization in any ItemsControl there are several properties that need to be correctly set .

- First you need to indicate that ScrollViewer content is able to manage scroll: <ItemsControl ScrollViewer.CanContentScroll="True".../>
- Then you have to use a panel to host items that can virtualize items, that would be a VirtualizingStackPanel.
- Enable virtualization in the VirtualizingStackPanel by setting IsVirtualizing="True" (it is the default value though), and configure the type of virtualization with VirtualizationMode and ScrollUnit properties.

The problem with TreeView is that virtualization only would work for the first level of items, the ones directly added to the TreeView. Sub items cannot be managed by TreeView's ScrollViewer+VirtualizingStackPanel, so when they are expanded all their sub-items create the corresponding containers and are added to the visual tree.

Completely virtualizing a TreeView is something we don't have implemented.

Re: Expanding treeview performent

Posted: 19 May 2017, 01:51
by PhiLong
Thank you for your explanation.

Do you have any plan to support virtualization on sub-items?

Re: Expanding treeview performent

Posted: 22 May 2017, 18:39
by sfernandez
Thank you for your explanation.

Do you have any plan to support virtualization on sub-items?
Sorry, but it is not planned to be included soon.

Re: Expanding treeview performent

Posted: 23 May 2017, 01:25
by jsantos
Do you think you could find a workaround for it? (like using a different type of container...)

Re: Expanding treeview performent

Posted: 23 May 2017, 04:32
by PhiLong
My scenario is loading a hierarchy data from a file and display it into a treeview. And it can be quickly scrolled to a selected node by code (BringIntoView).

The problem is, if the child node has too many items (~1500), it takes a few second to expand and scroll to that node.

Currently, I don't have any idea for a workaround in that situation. Can you give me a bit of advice?

Thank you all,
(sorry about my English)