我们遇到了 DataGridViews 的性能问题,其中重绘速度非常慢,并在此处找到了解决方案来创建派生类型并在控件上启用双缓冲。(派生类型是必需的,因为 DoubleBuffered 属性受到保护)
将 DoubleBuffered 属性设置为 true 似乎没有任何缺点。
我们遇到了 DataGridViews 的性能问题,其中重绘速度非常慢,并在此处找到了解决方案来创建派生类型并在控件上启用双缓冲。(派生类型是必需的,因为 DoubleBuffered 属性受到保护)
将 DoubleBuffered 属性设置为 true 似乎没有任何缺点。
我认为它的最佳解决方案:
typeof(DataGridView).InvokeMember(
"DoubleBuffered",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
null,
myDataGridViewObject,
new object[] { true });
在这里找到
它受到保护是因为 DGV 继承了 Control 的属性。并且 Control.DoubleBuffered 受到保护。这是有道理的,因为每个派生控件都应该自己决定打开它。而且控制用户随意开启或关闭也没有任何意义。DGV 设计师决定离开。
他们可能决定这样做的一个原因是双缓冲实际上会使绘画变慢。渲染缓冲区位图的额外步骤需要时间。它只是在人眼看来更快,你观察到突然出现的位图。您看不到绘制位图所需的时间。除非需要绘制其他控件并且在 DGV 之后轮到它们,否则它是非常可见的。
您看到的是首先绘制的表单,控件所在的位置有孔。这些孔有白色背景。使用 TransparencyKey 或 Opacity 属性时为黑色。然后,每个控件都会获得 Paint 事件,并一个接一个地填充这些孔。这种效果也被用户感知为闪烁,尽管它与 DoubleBuffered 解决的闪烁不同。当背景为黑色时尤其明显。
解决这个问题需要的是整个表单及其所有控件都是双缓冲的。这在 Windows 窗体中不可用。但是,Windows XP 和更高版本实际上支持这一点。检查这个线程,看看它是如何完成的。请注意,它可能会产生该线程中记录的副作用。
根据定义,双缓冲使用两个缓冲区和两倍的内存来渲染控件的视图。因此,那里有一些缺点,但是,由于您现在在 PC 中获得的内存量,可能没有多少人会注意到这种牺牲。
不知道为什么它受到保护。也许该功能在控件的早期版本中不可用,并且在引入它时设计人员不想更改控件的公共接口。或者他们认为这是一项高级功能,并希望限制新控制控件的方法的数量,以便能够使其做一些有用的事情。
在 datagridview 上打开双缓冲不需要继承。您可以通过反射现有的 datagridview 来做到这一点。