eng*_*mtm 1 c# wpf treeview virtualization
我有一个TreeView控件,允许用户根据关键字过滤树中的项目。VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling"我的树上有它并且它ItemsSource是数据绑定的。我TreeViewItem的Visibility设置如下:
<Setter Property="Visibility" Value="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"/>
该树在未过滤时的性能非常好,但在加载具有大量隐藏项目的树项目时,我发现性能受到很大影响。从我在 VS 的诊断工具中看到的情况来看,在我看来,MyTreeViewItem试图加载它的不可见子项,即使它们不可见,这会导致内存和 CPU 因加载大量不可见项而受到影响。有谁之前经历过这个吗?有没有办法可以覆盖实现虚拟树项目的默认逻辑,以便隐藏项目不会被加载?
此行为是预期的。
假设您的收藏中有 10000 件物品。前 5000 名已IsVisible设置为false。启用 UI 虚拟化后,会生成容器,直到填满可用空间。所以你最终会得到 5000 个折叠的TreeViewItems (它们不占用空间)加上几个填充可用空间的。我希望你能明白问题出在哪里。
我认为最好的选择是使用Live Shaping (在WPF 4.5中提供)。基本思想是从源集合视图中过滤掉不可见的项目,以便不会为这些项目生成容器。
简而言之,而不是
<TreeView ItemsSource="{Binding Items}">
</TreeViewitem>
Run Code Online (Sandbox Code Playgroud)
您可以使用以下设置:
<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>
Run Code Online (Sandbox Code Playgroud)
和
private void Items_Filter(object sender, FilterEventArgs e)
{
var item = (YourItemType)e.Item;
e.Accepted = item.IsVisible;
}
Run Code Online (Sandbox Code Playgroud)
您还必须将相同的技巧应用于HierarchicalDataTemplate.ItemsSource. 其作用是设置一个集合视图,用于侦听IsVisible属性的更改并在必要时重新应用过滤器(如果您使用的是4.5之前的WPF版本,则必须手动执行此操作)。