【发布时间】:2020-09-20 10:15:46
【问题描述】:
我有一个带有垂直滚动条的 WinForms TreeView。有时我必须重置节点并再次填充树。我在 BeginUpdate/EndUpdate 调用过程中执行此操作。但是当我调用 Nodes.Clear() 时,滚动条被重新计算以考虑节点的清除,并且在填充节点并调用 EndUpdate 之后再次重新计算。这会产生难看的闪烁。
treeView.BeginUpdate()
treeView.Nodes.Clear()
CreateNodes(treeView.Nodes)
treeView.EndUpdate()
我认为调用 BeginUpdate/EndUpdate 会阻止 TreeView 的所有重绘。那么问题是我的猜测是否错误,而事实并非如此,在这种情况下,解决方案应该是什么。
(我使用的是 Visual Basic,.NET 框架 4.6.1)
【问题讨论】:
-
这就是野兽的工作方式,你无能为力。我不会提到 LockWindowUpdate()。这通常不称为“闪烁”,您可能会抱怨 EndUpdate() 之后发生的重绘。将数百个节点填充到树中并不是一个好主意。也许双缓冲可以提供帮助,stackoverflow.com/a/10364283/17034
-
+ 请注意,如果您有超过 200 个节点,
treeView.Nodes.Clear()已经在所有者 TreeView 上调用了BeginUpdate()/EndUpdate(),因此您可能会调用它两次。EndUpdate()发送WM_SETREDRAW然后Invalidate()。你需要有很多节点才能看到这个效果。 +CreateNodes()在做什么是未定义的。 -
SendMessage(Parent.Handle, WM_SETREDRAW, False, 0)正是BeginUpdate()正在做的事情。在这种情况下,您可以防止重绘父对象。您的DrawItem程序缺少对引发事件时发生的情况的检查。这并不是什么新鲜事,它取决于 TreeView 绘制其项目的方式:您可能会多次收到同一项目的相同事件,也许,您忘记检查项目是什么或当时的节点状态。所以你在不应该画的时候画它。即使您知道发生了什么,该代码也需要大量调试。 -
你可以注意到,当你看到节点闪烁时,所有者绘制过程并不完美,即使你有非常几个项目。如果您单击一个节点并且您看到一个小的 运动 或感知到一个小的延迟,那么您的过程是不正确的:您正在绘制更多您应该绘制的内容。这很常见。