隐藏项

时间:2018-01-24 01:44:06

标签: c# wpf treeview virtualization

我有一个TreeView控件,我允许用户根据关键字过滤树的项目。我的树上有VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling",其ItemsSource是数据绑定的。我的TreeViewItem Visibility设置如下:

<Setter Property="Visibility" Value="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"/>

当树没有被过滤时,树的表现非常好,但是在加载具有大量隐藏项的树项时,我看到了很大的性能损失。从我在VS的诊断工具中可以看到,在我看来,My TreeViewItem尝试加载它的隐形子项,即使它们不可见,这也导致内存和CPU大量的加载了隐形物品。有谁之前经历过这个吗?有没有办法可以覆盖实现虚拟树项的默认逻辑,这样隐藏的项就不会被加载?

1 个答案:

答案 0 :(得分:2)

此行为是预期的。

假设您的收藏品中有10000件商品。 First 5000将IsVisible设置为false。启用UI虚拟化后,将生成容器,直到它们填满可用空间。所以你最终得到5000折叠TreeViewItem(他们没有空间)加上一对填满可用空间的人。我希望你能看出问题所在。

我认为您最好的选择是使用 Live Shaping (可在 WPF 4.5中找到)。基本思想是从源集合视图中过滤掉不可见的项目,以便不为这些项目生成容器。

简而言之,而不是

<TreeView ItemsSource="{Binding Items}">
</TreeViewitem>

您可以使用以下设置:

<TreeView>
    <FrameworkElement.Resources>
        <CollectionViewSource x:Key="Items"
                              Source="{Binding Items}"
                              Filter="Items_Filter"
                              IsLiveFilteringRequested="True"
                              xmlns:sys="clr-namespace:System;assembly=mscorlib">
            <CollectionViewSource.LiveFilteringProperties>
                <sys:String>IsVisible</sys:String>
            </CollectionViewSource.LiveFilteringProperties>
        </CollectionViewSource>
    </FrameworkElement.Resources>
    <ItemsControl.ItemsSource>
        <Binding Source="{StaticResource Items}" />
    </ItemsControl.ItemsSource>
</TreeView>

private void Items_Filter(object sender, FilterEventArgs e)
{
    var item = (YourItemType)e.Item;
    e.Accepted = item.IsVisible;
}

您还必须对HierarchicalDataTemplate.ItemsSource应用相同的技巧。 这样做是设置一个集合视图来监听IsVisible属性中的更改并在必要时重新应用过滤器(如果您在 4.5之前使用 WPF 版本你必须手动完成。