4

我一直在检查 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;
    }
}

如果我将 TreeView 替换为 ListBox,UI 虚拟化将按预期工作 - 即仅请求约 20 个项目,而不是全部 1000 个。

我在这里做错了吗?

编辑

我也尝试按照建议将默认值替换ItemsPanelVirtualizingStackPanel,但我得到了相同的结果。

4

1 回答 1

2

ItemsPanelTemplateTreeView 的默认设置是StackPanel,这不是VirtualizingStackPanel您在其中看不到虚拟化的原因。而对于 ListBox,默认 ItemsPanelTemplate 是 VirtualizingStackPanel,这就是设置VirtualizingStackPanel.IsVirtualizing="True"适用于 ListBox 的原因。

除了设置属性之外,要在 TreeView 上启用虚拟化VirtualizingStackPanel.IsVirtualizing="True",您需要像这样覆盖其默认 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>
于 2012-07-22T13:00:14.707 回答