winforms 为什么DataGridView的DoubleBuffered属性默认为false,为什么它受到保护?

sczxawaw  于 2023-01-26  发布在  其他
关注(0)|答案(4)|浏览(216)

我们遇到了DataGridViews的性能问题,重绘速度非常慢,找到了Here解决方案来创建派生类型并在控件上启用双缓冲。(派生类型是必需的,因为DoubleBuffered属性是受保护的)
将DoubleBuffered属性设置为true似乎没有任何缺点。

v440hwme

v440hwme1#

我认为最好的解决办法是:

typeof(DataGridView).InvokeMember(
   "DoubleBuffered", 
   BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
   null, 
   myDataGridViewObject, 
   new object[] { true });

找到here

lf5gs5x2

lf5gs5x22#

它是受保护的,因为DGV继承了Control的属性。而Control.DoubleBuffered是受保护的。这是有意义的,因为每个派生的控件都应该自己决定是否打开它。控件用户随意打开或关闭它是没有意义的。DGV设计者决定关闭它。
他们这样做的一个原因可能是双缓冲实际上会使绘制速度变慢。渲染缓冲位图的额外步骤会花费时间。它只是在人眼看来更快,你会观察到位图突然出现。你看不到绘制位图所花的时间。除非其他控件需要绘制,并且在DGV之后轮到它们,否则它是相当明显的。
你看到的是首先绘制的窗体,控件所在的位置有洞。这些洞有白色背景。当你使用TransparencyKey或Opacity属性时,背景是黑色的。然后每个控件都得到Paint事件,洞被一个接一个地填充。用户也会感觉到这种效果是 Flink 的。虽然这是一种不同的 Flink 从一个双缓冲解决。它是特别明显的背景是黑色。
解决这个问题所需要的是整个窗体,包括它的所有控件,都是双缓冲的。这在Windows窗体中是不可用的。然而,Windows XP和更高版本实际上支持这一点,他们称之为“复合”。将以下代码复制/粘贴到窗体类中的任何地方:

protected override CreateParams CreateParams {
    get {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;  // Turn on WS_EX_COMPOSITED
        return cp;
    }
}
li9yvcax

li9yvcax3#

根据定义,双缓冲使用两个缓冲区和两倍的内存来渲染控件的视图。因此,这是有一些缺点的,然而,以你现在在PC中获得的内存量,可能没有多少人会注意到这种牺牲。
不知道为什么它是受保护的。也许这个函数在控件的早期版本中是不可用的,当它被引入时,设计者不想改变控件的公共接口。或者也许他们认为这是一个高级特性,想限制新接触控件的人必须研究的方法的数量,以便能够使它做一些有用的事情。

5lwkijsr

5lwkijsr4#

turn on doublebuffering on a datagridview不需要继承,可以通过现有数据网格视图上的反射来实现。

相关问题