我有一个具有 2 级层次结构的 TreeView。 TreeView Item 已竞标特定类的属性。基本上我正在获取 ObservableCollection 列表并将该列表分配为我的 TreeView ItemsSource。最初 treeView 可见性设置为 Collapsed,在分配 ItemsSource 后,TreeView 可见性设置为 Visible。此时应用程序卡住了大约 40 秒(它基本上为每个父项加载了 1000 个父项和 5-10 个子项)。

后面的代码是

PopulateTreeView()
{
    // ocListToDisplay is my ObservableCollection
    tvES.ItemsSource = ocListToDisplay;

    //App Freezes at this bit when making the tvES Visible from Collapsed
    tvES.Visibility = System.Windows.Visibility.Visible;
}

我的 XAML 是这样的
 <ScrollViewer Name="scContainer" VerticalAlignment="Stretch"
               HorizontalAlignment="Stretch">
    <StackPanel>
        <StackPanel.Resources>
            <exportImport:TreeViewDashboard x:Key="dataItems"/>
            <HierarchicalDataTemplate DataType="{x:Type exportImport:TreeViewDashboard}"
                                      ItemsSource="{Binding Path=Components}">

                <Grid  Margin="2" >
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition ></ColumnDefinition>
                        <ColumnDefinition ></ColumnDefinition>
                        <ColumnDefinition ></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <CheckBox Name="checkbx" Grid.Column="0" Margin="2"
                              Tag="{Binding Path=Tag}"
                              Checked="OnCheck" Unchecked="OnUnCheck"></CheckBox>
                    <Image Margin="2" Grid.Column="1" Source="{Binding Path=ImageUrl}"
                           Height="14" Width="16" ></Image>
                    <TextBlock Margin="2" Grid.Column="2" Text="{Binding Path=Name}"
                              FontWeight="Bold" />
                </Grid>

                <HierarchicalDataTemplate.ItemTemplate>
                    <DataTemplate>
                        <Grid  Margin="2" >
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition ></ColumnDefinition>
                                <ColumnDefinition ></ColumnDefinition>
                                <ColumnDefinition ></ColumnDefinition>
                            </Grid.ColumnDefinitions>
                            <CheckBox Name="checkbx" Grid.Column="0" Margin="2"
                                      Tag="{Binding Path=Tag}"
                                      Checked="OnCheck" Unchecked="OnUnCheck"/>
                            <Image Margin="2" Grid.Column="1"
                                   Source="{Binding Path=ImageUrl}"
                                   Height="14" Width="16" />
                            <TextBlock Margin="2" Grid.Column="2"
                                  Text="{Binding Path=Name}" FontWeight="Bold" />
                        </Grid>
                    </DataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>

            </HierarchicalDataTemplate>
        </StackPanel.Resources>

        <--same result if you set IsVirtualizing to True/False App freezes for 40 sec-->
        <TreeView Name="tvES"  BorderThickness="0"
              ItemsSource="{Binding Source={StaticResource dataItems}}"
              VirtualizingStackPanel.IsVirtualizing="False"
              VirtualizingStackPanel.VirtualizationMode="Recycling"
              TreeViewItem.Expanded="item_Expanded"
              TreeViewItem.Collapsed="item_Collapsed" >
            <TreeView.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel/>
                </ItemsPanelTemplate>
            </TreeView.ItemsPanel>
            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="IsExpanded" Value="False" />
                </Style>
            </TreeView.ItemContainerStyle>
        </TreeView>
    </StackPanel>
 </ScrollViewer>

我还尝试在我的树 View 中获取视觉效果的数量。在 IsVisualizing="True"和 IsVisualizing="False" 的两种情况下,我得到相同数量的 Visuals 计数这清楚地表明我做错了什么。

从树中获取视觉计数的代码
  //In my case I am passing tvES as  DependencyObject
    private static int GetVisualCount(DependencyObject visual)
    {
        int visualCount = 1;
        int childCount = VisualTreeHelper.GetChildrenCount(visual);

        for (int i = 0; i < childCount; i++)
        {
            DependencyObject childVisual = VisualTreeHelper.GetChild(visual, i);
            visualCount += GetVisualCount(childVisual);
        }

        return visualCount;
    }

我最终得到了树 View ,但问题是我的应用程序在填充树 View 时卡住了..!!任何人都得到了解决这个问题?我有scollviewer,这会导致虚拟化问题吗?

PS:生成的 TreeView 是这样的,但有 1000 个相似的节点

更新 :

我正在阅读有关 VirtualizingStackPanel 的内容,其中说 - “StackPanel 中的虚拟化仅在面板中包含的项目控件创建其自己的项目容器时才会发生。您可以通过使用数据绑定(bind)来确保发生这种情况。在创建项目容器并将其添加到在项目控制方面,VirtualizingStackPanel 没有提供优于 StackPanel 的性能优势。”

如果我遵循的上述方法是正确的,有人可以建议我吗?我很确定我是在错误的一边..

最佳答案

您忘记设置 ScrollViewer.CanContentScroll=True 。那是用于虚拟化的 key。并将 IsVirtualizing 放回 true

关于WPF TreeView 和虚拟化问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22567126/

10-13 23:41