我有一个带有 VirtualizingStackPanel 的 TreeView。TreeView 有一个“级别 1”TreeViewItem,我将此 TreeViewItem 绑定到一个 10k 项列表。每个孩子也是另一个 TreeViewItem。
虚拟化效果很好,性能也很好,但是有个大问题。假设我在页面顶部并按 Ctrl-End 到底部,浏览器变为空白。如果我稍微滚动鼠标或调整浏览器大小,它会重新出现。
另一个大问题是:当我快速滚动到树的中间或底部时。假设我停在项目编号 5000。然后我无法展开子树视图项,浏览器只显示任何内容,直到我滚动或调整大小。
很感谢任何形式的帮助。以下是示例 xaml 和代码:
<Page x:Class="WpfBrowserApplication3.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="clr-namespace:WpfBrowserApplication3"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="Page1" DataContext="{StaticResource _mainViewModel}">
<Page.Resources>
<s:SingleToCollectionConverter x:Key="_collectionConverter"></s:SingleToCollectionConverter>
<DataTemplate x:Key="_level2Template">
<TreeViewItem Header="{Binding Order}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Order: "></TextBlock>
<TextBox Text="{Binding Order}"></TextBox>
</StackPanel>
</TreeViewItem>
</DataTemplate>
</Page.Resources>
<TreeView VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Standard">
<TreeViewItem Header="Level 1" ItemsSource="{Binding Level2List}" ItemTemplate="{StaticResource _level2Template}"></TreeViewItem>
</TreeView>
</Page>
public class MainViewModel
{
public MainViewModel()
{
Level2List = new List<Level2>();
for (int i = 0; i < 10000; i++)
{
Level2List.Add(new Level2(i));
}
}
public List<Level2> Level2List { get; set; }
}
public class Level2
{
public Level2(int order)
{
Order = order;
}
public int Order { get; set; }
}
我将 Visual Studio 2010 与 .Net 4 一起使用。另外,我确实注意到,如果我在 _level2Template 下设置 TreeViewItem 的高度和宽度,问题就消失了。但是在我的情况下设置高度不是一个选项,因为高度在实际应用程序中会有所不同。
更新:对我来说,这个问题的发生似乎很明显,因为子树视图项的高度可能会有所不同。或许这就是为什么TreeView默认不开启VirtualizingStackPanel,而DataGrid & ListBox默认开启的原因。不用说数据网格或列表框项的高度通常是不变的。
更新:我下载了 Telerik RadTreeView 的免费试用版并测试了虚拟化。这个问题在telerik radtreeview 中根本没有出现。可以多测试一下telerik,然后可能会继续使用它。