'WPF treeview sub nodes disappeared
I'm new to wpf and xaml. I just built 4 complex tree views on separate tabs with the same type, data of which were loaded from a json file which is fixed. But I found something weird:
- When the first time they are loaded, some nodes do not show the little triangle, which means it contains no sub items, but in fact they do. (I have a number on the parent node and it says "10").
- This happens only on those nodes that are not in the viewable area of the tree. Which means if I scroll to the node, and then reload the tree, everything is ok. But if I scroll to a node which was not viewable when tree was loaded, there is a big chance that it does not show the triangle and sub items.
- When I switch among those tabs, sometimes a tree changes as described above, even no scrolling happens.
- Initialing the nodes with IsExpand = True / False does not make difference.
Here is the xaml:
<resultTrees:ResultTreeView x:Class="ChiSharedFormsWpf.ResultTrees.ChiTreeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:fa5="http://schemas.fontawesome.com/icons/"
xmlns:bsiIndexes="clr-namespace:ChiLibApiJson.BsiIndexes;assembly=ChiLibApiJson"
xmlns:dirTrees="clr-namespace:WpfUtilities.DirTrees;assembly=WpfUtilities"
xmlns:resultTrees="clr-namespace:ChiSharedFormsWpf.ResultTrees"
mc:Ignorable="d" FontFamily="Consolas"
MouseDoubleClick="ChiTreeView_OnMouseDoubleClick"
d:DesignHeight="450" Width="auto">
<Grid>
<DockPanel HorizontalAlignment="Stretch">
<TreeView Name="Tree" HorizontalAlignment="Stretch"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<TreeView.Resources>
<!-- Style the inactive selection the same as active -->
<SolidColorBrush Color="LightBlue" x:Key="{x:Static SystemColors.HighlightBrushKey}" />
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
Color="LightBlue" />
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}"
Color="OrangeRed" />
<HierarchicalDataTemplate DataType="{x:Type dirTrees:BriefTree}"
ItemsSource="{Binding Items}">
<StackPanel>
<StackPanel Orientation="Horizontal">
<fa5:FontAwesome Icon="{Binding Icon}" Margin="0,2,5,0" />
<TextBlock Text="{Binding Root.Text}" FontFamily="微软雅黑, Consolas" />
</StackPanel>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type resultTrees:FileResultList}"
ItemsSource="{Binding FileResultBriefs}">
<StackPanel Orientation="Horizontal"
MouseRightButtonUp="TreeNode_OnMouseRightButtonUp">
<fa5:FontAwesome Icon="{Binding Icon}" Margin="0,2,5,0" />
<TextBlock FontWeight="Bold" Text="{Binding Root.Text}" />
<TextBlock FontWeight="Bold" Text="{Binding FileResultBriefs.Count}" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type dirTrees:DirAndFileResultTree}"
ItemsSource="{Binding SubDirsAndFilesAndBadSmells}">
<StackPanel Orientation="Horizontal" Background="{Binding DirColorHex}"
MouseRightButtonUp="TreeNode_OnMouseRightButtonUp"
Tag="{Binding Root.DirName }">
<fa5:FontAwesome Icon="Regular_FolderOpen" Margin="0,2,5,0" />
<TextBlock FontWeight="Bold" Text="{Binding Index.Brief}" />
<TextBlock FontWeight="Bold" Text="{Binding Root.DirName}" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type dirTrees:FileResultBrief}"
ItemsSource="{Binding BadSmells}">
<StackPanel Orientation="Horizontal" Background="{Binding Index.SoftColorHex}"
MouseLeftButtonDown="FileResult_OnMouseLeftButtonDown"
MouseRightButtonUp="TreeNode_OnMouseRightButtonUp"
Tag="{Binding FileName}">
<fa5:FontAwesome Icon="Regular_FileCode" Margin="0,2,5,0" />
<TextBlock Text="{Binding Brief}" />
<TextBlock Text="{Binding FileName}" Margin="10 0"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type bsiIndexes:BadSmell}" ItemsSource="{Binding }">
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Style.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=IsWarning }"
Value="True">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
</Style.Triggers>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<StackPanel Orientation="Horizontal"
MouseLeftButtonDown="BadSmell_OnMouseLeftButtonDown"
Tag="{Binding}">
<fa5:FontAwesome Icon="{Binding XamlIcon}"
Foreground="{Binding Path=ForeColorHex}" Margin="0,2,5,0" />
<StackPanel>
<TextBlock Text="{Binding Path=LevelAndRuleNameAndExplanation}"
FontFamily="微软雅黑, Consolas"
Foreground="{Binding Path=ForeColorHex}" />
<TextBlock Text="{Binding Path=PositionAndDescription}"
FontFamily="微软雅黑, Consolas"
Foreground="{Binding Path=ForeColorHex}" />
</StackPanel>
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type dirTrees:BriefString}">
<TextBlock Text="{Binding Path=Text}" Foreground="{Binding Path=ForeColorHex}"
FontFamily="微软雅黑, Consolas" />
</DataTemplate>
<DataTemplate DataType="{x:Type dirTrees:IgnoredDirString}">
<StackPanel MouseRightButtonUp="TreeNode_OnMouseRightButtonUp"
Tag="{Binding Text}" Orientation="Horizontal">
<fa5:FontAwesome Icon="Solid_Folder" Foreground="gray"></fa5:FontAwesome>
<TextBlock Text="{Binding Path=Text}" Foreground="gray"
TextDecorations="Strikethrough"
FontFamily="微软雅黑, Consolas" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type dirTrees:IgnoredFileString}">
<StackPanel MouseRightButtonUp="TreeNode_OnMouseRightButtonUp"
Tag="{Binding Text}" Orientation="Horizontal">
<fa5:FontAwesome Icon="Regular_File" Foreground="gray"></fa5:FontAwesome>
<TextBlock Text="{Binding Path=Text}" Foreground="gray"
TextDecorations="Strikethrough"
FontFamily="微软雅黑, Consolas" />
</StackPanel>
</DataTemplate>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<!-- <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=OneTime}" /> -->
<!-- <Setter Property="IsExpanded" Value="True" /> -->
<Setter Property="IsExpanded" Value="False" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
</DockPanel>
</Grid>
</resultTrees:ResultTreeView>
Here is partial of the model:
public List<FileResultBrief> FileResultBriefs { get; set; } = new();
public List<DirAndFileResultTree> SubTrees { get; set; } = new();
[JsonIgnore]
public IList SubDirsAndFilesAndBadSmells => new CompositeCollection
{
new CollectionContainer {Collection = IgnoredFiles.OrderBy(i => i.Text).ToList()},
new CollectionContainer {Collection = FileResultBriefs},
new CollectionContainer {Collection = IgnoredDirs.OrderBy(i => i.Text).ToList()},
new CollectionContainer {Collection = SubTrees},
};
So far I highly adoubt that there might be some shared-reference error in the model. But I someone can figure out problems in the xaml would be really helpful. Because I know little of it's mechanism.
Thanks a lot.
Solution 1:[1]
Finally, removing
VirtualizingStackPanel.VirtualizationMode="Recycling"
or using
VirtualizingStackPanel.VirtualizationMode="Standard"
instead solves the problem. I added this line 2 weeks ago to improve the performance. According to https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.virtualizationmode?view=windowsdesktop-6.0, seems that if a treeview contains different kind of containers (which I think is almost always true) should not use recycling mode.
So it's design for list only?
And I adapted o_w's suggestion and change the list to ObservableList. It makes no difference in this case but might help later, thanks.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | cheny |
