WinForms中的ListView和TreeView:奇怪的性能问题

3
当我们优化项目中的用户界面时,我注意到ListView中出现了非常奇怪的提速,而且不知道它从何而来。
只是简单地在listView(视图:列表)中添加5000个元素 - 3815毫秒:
for (int i = 0; i < 5000; i++)
         listView1.Items.Add((Guid.NewGuid().ToString()));

使用BeginUpdate() + EndUpdate() - 2317毫秒:

listView1.BeginUpdate();
for (int i = 0; i < 5000; i++)
    listView1.Items.Add((Guid.NewGuid().ToString()));
listView1.EndUpdate();

使用Hide() + Show() - 163毫秒(毫无疑问,比原来快10倍以上):

listView1.Hide();
for (int i = 0; i < 5000; i++)
    listView1.Items.Add((Guid.NewGuid().ToString()));
listView1.Show();

为什么这种方式如此快速? 此外,为什么从隐藏的ListView (可见性:false) 开始,在填充后显示它并没有同样的性能提升呢?

TreeView是不同的。简单添加5000个节点-2130毫秒:

for (int i = 0; i < 5000; i++)
    treeView1.Nodes.Add((Guid.NewGuid().ToString()));

使用Hide() + Show()方法 - 1048毫秒:

treeView1.Hide();
for (int i = 0; i < 5000; i++)
    treeView1.Nodes.Add((Guid.NewGuid().ToString()));
treeView1.Show();

使用BeginUpdate() + EndUpdate() - 291毫秒:

treeView1.BeginUpdate();
for (int i = 0; i < 5000; i++)
    treeView1.Nodes.Add((Guid.NewGuid().ToString()));
treeView1.EndUpdate();

1
将您的项目添加到列表中,然后调用 AddRange(...)。此外,您应该手动指定列,而不是信任控件动态分配它们。 - Seph
2个回答

2
似乎是一个bug。当控件被隐藏时,它不会在添加项目时计算它们的范围(类似于Graphics.MeasureString或其本地等效项),这是有道理的。当控件显示后,它也不会稍后计算,这可能是一个bug。因此,您会得到4列而不是2列。请注意,当您获得2列时,项目不会被截断,因为已执行此大小计算。当您获得4列时,显示通常不正确。
那么为什么从一开始就不让它处于不可见状态呢?原因是,在这种情况下,直到调用Show方法或进行任何强制创建句柄(底层Win32控件尚未创建)的操作之前,控件的句柄不会被创建。然后,Show将首次创建句柄,执行大量其他代码,包括OnHandleCreated,并且在此时点上的代码组织项目并计算其大小。
如果控件从一开始就不可见,可以检查IsHandleCreated属性是否为false
您还可以显式创建句柄,即通过尝试读取Handle属性(这会强制创建句柄),然后它的行为方式相同-速度很快,但显示不正确:
IntPtr handle = listView1.Handle;
for (int i = 0; i < 5000; i++)
    listView1.Items.Add((Guid.NewGuid().ToString()));
listView1.Show();

如果句柄早已创建,那么 OnHandleCreated 以及大小计算也会被调用,但此时列表为空。

0
因为如果您在不隐藏ListView的情况下添加元素,它会逐个绘制元素,当您隐藏ListView时,它将一次性绘制所有元素。

真正的问题是: 为什么从隐藏的ListView(Visible:false)开始,在填充后显示它并不能带来相同的性能提升?为什么隐藏/显示会改变可见列数? - Kuba
相同的答案..因为,如果每个元素都可见,则添加的每个元素都会单独绘制(在添加新元素后调用draw)..但是,如果隐藏组件并在之后显示,则会一次性绘制所有元素(添加所有元素,然后将其全部绘制在GUI上)。 - Eduard Baraniak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接