我一直在检查 WPF 的 TreeView 控件的 UI 虚拟化功能,据我所知,它从 .NET 3.5 SP1 开始可用。
我做了一个简单的项目来确保正确执行 UI 虚拟化,但发现它根本不起作用 - 所有项目都被检索,而不仅仅是当前显示在屏幕上的项目。
我的 XAML 看起来像这样
<TreeView x:Name="myTree" Height="150" ItemsSource="{Binding Items}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Standard"
ScrollViewer.IsDeferredScrollingEnabled="True" />
而我背后的代码
public IEnumerable Items { get; set; }
public MainWindow()
{
Items = GenerateList();
this.DataContext = this;
InitializeComponent();
}
private IEnumerable GenerateList()
{
MyList list = new MyList();
for (int i = 0; i < 1000; i++)
{
list.Add("Item " + i);
}
return list;
}
请注意,
MyList
是我自己的 IList
实现,它包含一个 ArrayList
并且仅将调用转发到持有的 ArrayList
并将调用的方法/属性写入控制台。例如:public object this[int index]
{
get
{
Debug.WriteLine(string.Format("get[{0}]", index));
return _list[index];
}
set
{
Debug.WriteLine(string.Format("set[{0}]", index));
_list[index] = value;
}
}
如果我用 ListBox 替换我的 TreeView,UI 虚拟化会按预期工作 - 即只请求约 20 个项目,而不是整个 1000 个。
我在这里做错了吗?
编辑
我也尝试按照建议将默认的
ItemsPanel
替换为 VirtualizingStackPanel
,但我得到了相同的结果。 最佳答案
TreeView 的默认 ItemsPanelTemplate
是 StackPanel
而不是 VirtualizingStackPanel
这就是为什么你看不到其中的虚拟化。而对于 ListBox,默认 ItemsPanelTemplate 是 VirtualizingStackPanel,这就是为什么设置 VirtualizingStackPanel.IsVirtualizing="True"
适用于 ListBox。
除了设置属性 VirtualizingStackPanel.IsVirtualizing="True"
之外,要在 TreeView 上启用虚拟化,您需要像这样覆盖其默认 itemsPanelTemplate -
<TreeView x:Name="myTree" Height="150" ItemsSource="{Binding Items}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Standard"
VirtualizingStackPanel.CleanUpVirtualizedItem="myTree_CleanUpVirtualizedItem"
ScrollViewer.IsDeferredScrollingEnabled="True">
<TreeView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</TreeView.ItemsPanel>
</TreeView>
关于c# - TreeView 不执行 UI 虚拟化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11600323/