我有一个用C#编写的遗留应用程序,它显示了一个非常复杂的树视图,包含1万到2万个元素。过去我遇到过类似的问题(但在C++中),我用Win32 API提供的OWNERDATA功能解决了这个问题。C#中是否有类似的机制?编辑:计划是优化创建时间和浏览时间。通过Win32 API可用的方法在这两种情况下都是非常好的,因为它将初始化时间减少到零,并且对元素的请求数量被限制为在任何一个时间都只能看到。Joshl:我们实际上已经完全按照你的建议做了,但我们还需要更高的效率。
nimxete21#
提高性能的一种方法是在用户展开树视图时加载TreeNodes。通常,用户不需要在屏幕上一次打开20,000个节点。只加载用户需要看到的级别,沿着向用户正确显示可见性所需的任何子信息(如果存在子节点,则展开图标、计数、图标等)。当用户展开节点时,及时加载子节点。基思的提示:对于winforms TreeView,您需要至少有一个子节点,否则它将不会显示expand [+],但随后您将处理TreeNodeExpanded事件以删除该伪节点并填充子节点。
0mkxixxg2#
在我们的主WinForm应用程序中,我们有一个一次性加载的树视图:
而且到目前为止性能还是不错的。它实际上是我们不会用第三方组件替换的少数组件之一。根据我的经验,当您加载节点(一次性或按需)而不调用开始/EndUpdate()时,TreeView的性能会变慢,特别是在节点已排序的情况下,但是如果正确调用了Begin/EndUpdate(),则不会出现与组件本身相关的性能问题。
wh6knrhe3#
我不相信.NET TreeView支持您想要的,尽管.NET的DataGridView支持这种类型的模型(请参阅DataGridView的VirtualMode属性)。TreeView允许您绘制自己的节点,但不允许您从某个虚拟存储区填充它们。如果可能,您可能要考虑在应用程序中使用DataGridView。(就像上面提到的joshl)可能会起作用,如果你能绕过一些问题,当节点展开时正确地刷新屏幕。除此之外,你可能想看看一些第三方供应商,比如this one (Divelements SandGrid),可能(强调可能)支持您所需的操作模式。注:截至2013年7月底,Divelements不支持SandGrid。
knpiaxh14#
当我在过去做类似的事情时,我倾向于选择天真的惰性加载风格。
TreeNode.Tag
TreeView.BeforeExpand
TreeView.AfterCollapse
TreeNode
BeforeExpand
k2fxgqgv5#
有一种方法可以使TreeView的性能更好,那就是创建所有的子节点并将它们连接在一起**,然后**将节点添加到TreeView中。如果这是我们所讨论的图形性能的话。
TreeView tree = new TreeView(); TreeNode root = new TreeNode("Root"); PopulateRootNode(root); // Get all your data tree.Nodes.Add(root);
否则,请使用OnTreeNodeExpanded逐个节点加载它们。
ca1c2owp6#
对于Windows C#编程中的大数据,无论是在WPF还是WinForms中,我通常都是动态添加节点。我加载初始的树根+子节点+孙节点。当展开任何节点时,我加载表示展开节点的孙节点(如果有)的树节点。此模式也适用于数据检索。如果您确实要从包含数千条或数百万条记录的源加载数据,您可能不希望预先加载所有这些记录。没有用户希望等待这些记录被加载,也没有理由加载可能从未查看过的数据。我通常在后台线程上根据需要加载孙节点或曾孙节点数据,然后将这些数据封送回UI线程,并创建和添加节点。这使UI具有响应性。您可以直观地装饰树节点,以指示它们仍在加载,以应对用户先于您的IO访问数据存储的情况。
hc2pp10m7#
这对我很有效(CSharp):
Visible = false; ... Visible = true;
在我的例子中(2000个节点),只需要1~2秒就可以加载树,这比其他任何方法都要快得多。在C++中可能会工作得很好。
7条答案
按热度按时间nimxete21#
提高性能的一种方法是在用户展开树视图时加载TreeNodes。通常,用户不需要在屏幕上一次打开20,000个节点。只加载用户需要看到的级别,沿着向用户正确显示可见性所需的任何子信息(如果存在子节点,则展开图标、计数、图标等)。当用户展开节点时,及时加载子节点。
基思的提示:对于winforms TreeView,您需要至少有一个子节点,否则它将不会显示expand [+],但随后您将处理TreeNodeExpanded事件以删除该伪节点并填充子节点。
0mkxixxg2#
在我们的主WinForm应用程序中,我们有一个一次性加载的树视图:
而且到目前为止性能还是不错的。它实际上是我们不会用第三方组件替换的少数组件之一。
根据我的经验,当您加载节点(一次性或按需)而不调用开始/EndUpdate()时,TreeView的性能会变慢,特别是在节点已排序的情况下,但是如果正确调用了Begin/EndUpdate(),则不会出现与组件本身相关的性能问题。
wh6knrhe3#
我不相信.NET TreeView支持您想要的,尽管.NET的DataGridView支持这种类型的模型(请参阅DataGridView的VirtualMode属性)。TreeView允许您绘制自己的节点,但不允许您从某个虚拟存储区填充它们。
如果可能,您可能要考虑在应用程序中使用DataGridView。(就像上面提到的joshl)可能会起作用,如果你能绕过一些问题,当节点展开时正确地刷新屏幕。除此之外,你可能想看看一些第三方供应商,比如this one (Divelements SandGrid),可能(强调可能)支持您所需的操作模式。
注:截至2013年7月底,Divelements不支持SandGrid。
knpiaxh14#
当我在过去做类似的事情时,我倾向于选择天真的惰性加载风格。
TreeNode.Tag
属性保存可用于查找子级的引用TreeView.BeforeExpand
事件填充子节点TreeView.AfterCollapse
事件来移除它们。TreeNode
,将其作为子节点添加到所有未填充的节点中,然后在填充BeforeExpand
之前检查其是否存在。k2fxgqgv5#
有一种方法可以使TreeView的性能更好,那就是创建所有的子节点并将它们连接在一起**,然后**将节点添加到TreeView中。如果这是我们所讨论的图形性能的话。
否则,请使用OnTreeNodeExpanded逐个节点加载它们。
ca1c2owp6#
对于Windows C#编程中的大数据,无论是在WPF还是WinForms中,我通常都是动态添加节点。我加载初始的树根+子节点+孙节点。当展开任何节点时,我加载表示展开节点的孙节点(如果有)的树节点。
此模式也适用于数据检索。如果您确实要从包含数千条或数百万条记录的源加载数据,您可能不希望预先加载所有这些记录。没有用户希望等待这些记录被加载,也没有理由加载可能从未查看过的数据。
我通常在后台线程上根据需要加载孙节点或曾孙节点数据,然后将这些数据封送回UI线程,并创建和添加节点。这使UI具有响应性。您可以直观地装饰树节点,以指示它们仍在加载,以应对用户先于您的IO访问数据存储的情况。
hc2pp10m7#
这对我很有效(CSharp):
在我的例子中(2000个节点),只需要1~2秒就可以加载树,这比其他任何方法都要快得多。在C++中可能会工作得很好。