winforms C#中的慢速树状检视

nfg76nw0  于 2022-11-17  发布在  C#
关注(0)|答案(7)|浏览(145)

我有一个用C#编写的遗留应用程序,它显示了一个非常复杂的树视图,包含1万到2万个元素。
过去我遇到过类似的问题(但在C++中),我用Win32 API提供的OWNERDATA功能解决了这个问题。
C#中是否有类似的机制?
编辑:计划是优化创建时间和浏览时间。通过Win32 API可用的方法在这两种情况下都是非常好的,因为它将初始化时间减少到零,并且对元素的请求数量被限制为在任何一个时间都只能看到。Joshl:我们实际上已经完全按照你的建议做了,但我们还需要更高的效率。

nimxete2

nimxete21#

提高性能的一种方法是在用户展开树视图时加载TreeNodes。通常,用户不需要在屏幕上一次打开20,000个节点。只加载用户需要看到的级别,沿着向用户正确显示可见性所需的任何子信息(如果存在子节点,则展开图标、计数、图标等)。当用户展开节点时,及时加载子节点。
基思的提示:对于winforms TreeView,您需要至少有一个子节点,否则它将不会显示expand [+],但随后您将处理TreeNodeExpanded事件以删除该伪节点并填充子节点。

0mkxixxg

0mkxixxg2#

在我们的主WinForm应用程序中,我们有一个一次性加载的树视图:

  • 开始更新()
  • 加载20,000个节点
  • 结束更新()

而且到目前为止性能还是不错的。它实际上是我们不会用第三方组件替换的少数组件之一。
根据我的经验,当您加载节点(一次性或按需)而不调用开始/EndUpdate()时,TreeView的性能会变慢,特别是在节点已排序的情况下,但是如果正确调用了Begin/EndUpdate(),则不会出现与组件本身相关的性能问题。

wh6knrhe

wh6knrhe3#

我不相信.NET TreeView支持您想要的,尽管.NET的DataGridView支持这种类型的模型(请参阅DataGridView的VirtualMode属性)。TreeView允许您绘制自己的节点,但不允许您从某个虚拟存储区填充它们。
如果可能,您可能要考虑在应用程序中使用DataGridView。(就像上面提到的joshl)可能会起作用,如果你能绕过一些问题,当节点展开时正确地刷新屏幕。除此之外,你可能想看看一些第三方供应商,比如this one (Divelements SandGrid),可能(强调可能)支持您所需的操作模式。
注:截至2013年7月底,Divelements不支持SandGrid。

knpiaxh1

knpiaxh14#

  • 注意:这个答案是无效的编辑的提问者说,他已经做了这种事情,但我决定仍然张贴它供未来参考的其他搜索这个主题 *

当我在过去做类似的事情时,我倾向于选择天真的惰性加载风格。

  • 使用TreeNode.Tag属性保存可用于查找子级的引用
  • 使用TreeView.BeforeExpand事件填充子节点
  • 也可以使用TreeView.AfterCollapse事件来移除它们。
  • 要使[+]/[-]框出现,我发现的最好方法是创建一个单独的虚拟TreeNode,将其作为子节点添加到所有未填充的节点中,然后在填充BeforeExpand之前检查其是否存在。
k2fxgqgv

k2fxgqgv5#

有一种方法可以使TreeView的性能更好,那就是创建所有的子节点并将它们连接在一起**,然后**将节点添加到TreeView中。如果这是我们所讨论的图形性能的话。

TreeView tree = new TreeView();
TreeNode root = new TreeNode("Root");
PopulateRootNode(root); // Get all your data
tree.Nodes.Add(root);

否则,请使用OnTreeNodeExpanded逐个节点加载它们。

ca1c2owp

ca1c2owp6#

对于Windows C#编程中的大数据,无论是在WPF还是WinForms中,我通常都是动态添加节点。我加载初始的树根+子节点+孙节点。当展开任何节点时,我加载表示展开节点的孙节点(如果有)的树节点。
此模式也适用于数据检索。如果您确实要从包含数千条或数百万条记录的源加载数据,您可能不希望预先加载所有这些记录。没有用户希望等待这些记录被加载,也没有理由加载可能从未查看过的数据。
我通常在后台线程上根据需要加载孙节点或曾孙节点数据,然后将这些数据封送回UI线程,并创建和添加节点。这使UI具有响应性。您可以直观地装饰树节点,以指示它们仍在加载,以应对用户先于您的IO访问数据存储的情况。

hc2pp10m

hc2pp10m7#

这对我很有效(CSharp):

Visible = false;
    ...
    Visible = true;

在我的例子中(2000个节点),只需要1~2秒就可以加载树,这比其他任何方法都要快得多。在C++中可能会工作得很好。

相关问题