您只需要根据DataGridView创建一个自定义类,以便启用其DoubleBuffering.而已!
class CustomDataGridView: DataGridView { public CustomDataGridView() { DoubleBuffered = true; } }
只要我的所有网格实例都使用这个自定义版本,一切都很好.如果我遇到由此引起的情况,我无法使用子类解决方案(如果我没有代码),我想我可以尝试将该控件注入表单:)(虽然我'将更有可能尝试使用反射来强制从外部启用DoubleBuffered属性再次避免依赖).
令人遗憾的是,这么简单的事情花了我很多时间......
注意:将答案作为答案,以便将问题标记为已回答
您只需要根据DataGridView创建一个自定义类,以便启用其DoubleBuffering.而已!
class CustomDataGridView: DataGridView { public CustomDataGridView() { DoubleBuffered = true; } }
只要我的所有网格实例都使用这个自定义版本,一切都很好.如果我遇到由此引起的情况,我无法使用子类解决方案(如果我没有代码),我想我可以尝试将该控件注入表单:)(虽然我'将更有可能尝试使用反射来强制从外部启用DoubleBuffered属性再次避免依赖).
令人遗憾的是,这么简单的事情花了我很多时间......
注意:将答案作为答案,以便将问题标记为已回答
下面是一些使用反射设置属性的代码,没有像Benoit建议的子类化.
typeof(DataGridView).InvokeMember( "DoubleBuffered", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, myDataGridViewObject, new object[] { true });
对于在VB.NET中搜索如何操作的人,这里是代码:
DataGridView1.GetType.InvokeMember("DoubleBuffered", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.SetProperty, Nothing, DataGridView1, New Object() {True})
添加到以前的帖子,对于Windows窗体应用程序,这是我用于DataGridView组件以使它们快速的.DrawingControl类的代码如下.
DrawingControl.SetDoubleBuffered(control) DrawingControl.SuspendDrawing(control) DrawingControl.ResumeDrawing(control)
在构造函数中的InitializeComponent()之后调用DrawingControl.SetDoubleBuffered(control).
在进行大数据更新之前调用DrawingControl.SuspendDrawing(控件).
在进行大数据更新后调用DrawingControl.ResumeDrawing(控件).
最后2个最好用try/finally块完成.(或者甚至更好地重写类,IDisposable
并SuspendDrawing()
在构造函数ResumeDrawing()
中调用Dispose()
.)
using System.Runtime.InteropServices; public static class DrawingControl { [DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam); private const int WM_SETREDRAW = 11; ////// Some controls, such as the DataGridView, do not allow setting the DoubleBuffered property. /// It is set as a protected property. This method is a work-around to allow setting it. /// Call this in the constructor just after InitializeComponent(). /// /// The Control on which to set DoubleBuffered to true. public static void SetDoubleBuffered(Control control) { // if not remote desktop session then enable double-buffering optimization if (!System.Windows.Forms.SystemInformation.TerminalServerSession) { // set instance non-public property with name "DoubleBuffered" to true typeof(Control).InvokeMember("DoubleBuffered", System.Reflection.BindingFlags.SetProperty | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic, null, control, new object[] { true }); } } ////// Suspend drawing updates for the specified control. After the control has been updated /// call DrawingControl.ResumeDrawing(Control control). /// /// The control to suspend draw updates on. public static void SuspendDrawing(Control control) { SendMessage(control.Handle, WM_SETREDRAW, false, 0); } ////// Resume drawing updates for the specified control. /// /// The control to resume draw updates on. public static void ResumeDrawing(Control control) { SendMessage(control.Handle, WM_SETREDRAW, true, 0); control.Refresh(); } }
答案对我也有用.我想我会添加一个改进,我认为应该是实施解决方案的任何人的标准做法.
该解决方案很有效,除非在远程桌面下作为客户端会话运行UI,尤其是在可用网络带宽较低的情况下.在这种情况下,通过使用双缓冲可以使性能变差.因此,我建议以下作为更完整的答案:
class CustomDataGridView: DataGridView { public CustomDataGridView() { // if not remote desktop session then enable double-buffering optimization if (!System.Windows.Forms.SystemInformation.TerminalServerSession) DoubleBuffered = true; } }
有关更多详细信息,请参阅检测远程桌面连接