WPF TreeView和虚拟化问题

时间:2014-03-21 18:47:09

标签: wpf xaml treeview virtualization

我有一个具有2级层次结构的TreeView。 TreeView项目已经绑定到特定类的属性。基本上我得到ObservableCollection列表并将该列表指定为我的TreeView ItemsSource。最初将treeView可见性设置为Collapsed,并在分配ItemsSource后,将TreeView可见性设置为Visible。此时app冻结了大约40秒(它基本上加载了1000个父项,每个父项加了5-10个孩子)。

代码behinnd

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>

我还尝试在树视图中获取视觉效果的数量。在 IsVisualizing =&#34; True&#34;的情况下,我得到相同数量的视觉效果。和IsVisualizing =&#34; False&#34; 这清楚地表明我做错了什么。

从树中获取视觉计数的代码

  //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;
    } 

我最终获得了树视图,但问题是我的应用程序冻结了填充树视图.. !!有人为此得到了工作量吗?我有scollviewer,这会导致虚拟化问题吗?

PS:TreeView Generated是这样的,但有1000个类似节点

enter image description here

更新

我正在阅读VirtualizingStackPanel,它说 - &#34; StackPanel中的虚拟化只发生在面板中包含的items控件创建自己的项容器时。您可以使用数据绑定来确保这种情况发生。在创建项容器并将其添加到items控件的情况下,VirtualizingStackPanel与StackPanel相比没有任何性能优势。&#34;

有人建议我,如果我遵循的上述方法是正确的?我非常确定我是在错误的一面..

1 个答案:

答案 0 :(得分:2)

您忘了设置ScrollViewer.CanContentScroll=True。这是虚拟化的key。并将IsVirtualizing放回true