如何提高DataGridView的绘制性能?

20

我有一个严重的问题,就是当DataGridView重新绘制时性能很差。

我使用DataGridView显示来自外部应用程序流的日志。流中的消息频率很高(小于1毫秒)。如果每次收到新消息时立即向DataGridView添加新行,则DataGridView没有足够的时间在下一条消息到来之前重新绘制自己。

一种可能的解决方案是使用队列来收集消息,并且每100毫秒使用队列中的消息重新绘制DataGridView。这很好,但是DataGridView在自动滚动到最后一行时会闪烁。(平滑滚动被禁用)

您能帮助我提高DataGridView的性能吗?


6个回答

47

最近我在使用DataGridView时遇到了一些缓慢的问题,解决方法是以下代码:

public static void DoubleBuffered(this DataGridView dgv, bool setting)
{
    Type dgvType = dgv.GetType();
    PropertyInfo pi = dgvType.GetProperty("DoubleBuffered",
          BindingFlags.Instance | BindingFlags.NonPublic);
    pi.SetValue(dgv, setting, null);
}

这会为DataGridView对象打开双缓冲。只需在您的DGV上调用DoubleBuffered()即可。希望能有所帮助。

编辑:我可能是从SO上找到这个代码的,但现在无法搜索原始代码,因此这只是强调代码不是我的。


9
您发布的方法使用反射来更改DataGridView控件上的非公共属性。这是一个可接受的解决方案,但更清晰的方法可能是继承现有的DataGridView控件并创建具有设置了“DoubleBuffered”样式的自定义控件。 - Cody Gray
我的问题是,如果我派生自己的控件,那么编辑器中的窗体将无法显示。 - Andrew Truckle

9

您是否已经为网格视图启用了双缓冲?

可以查看此处,获取一些想法,以改善数据网格视图的绘制性能。

如果还没有启用,请参考上述链接中的建议。


7

不使用反射的简洁解决方案是:

public class DataGridViewDoubleBuffered : DataGridView
{
   public DataGridViewDoubleBuffered()
   {
       DoubleBuffered = true;
   }
}

然后转到myForm.designer.cs并将类型从DataGridView更改为DataGridViewDoubleBuffered。


1
如果您在解决方案资源管理器中展开MyForm.cs,您可以打开MyForm.Designer.cs并使其实例化双缓冲子类而不是基类。 - Timo
3
谢谢您提供的内容-这是天差地别的改变。对于任何想知道如何做到这一点的人-请在代码底部添加此类-我将其添加到我的表单类之外的命名空间中。然后,打开您的表单Designer.CS(Form1.Designer.cs)并点击Windows Form Designer generated code旁边的+符号以取消隐藏该部分。更改datagridview初始化(类似于 this.dataGridView1 = new System.Windows.Forms.DataGridView)-将其更改为 this.dataGridView1 = new DataGridViewDoubleBuffered。然后,向下滚动到其声明的底部。 - user1274820
2
将声明 (private System.Windows.Forms.DataGridView dataGridView1) 更改为 private DataGridViewDoubleBuffered dataGridView1。我还将我的窗体设置为双缓冲 - 可能值得这样做 - 不确定是否必要。 - user1274820

3

3
当处理大量数据时,DataGridView控件可能会消耗大量内存开销,除非你小心使用。在内存有限的客户端上,可以通过避免高内存成本的功能来避免部分开销。您还可以使用虚拟模式自己管理部分或所有的数据维护和检索任务,以便为您的场景自定义内存使用情况。更多详细信息请访问dapfor.com。

3

我使用了这个解决方案并发现问题已经得到了修复。

在代码中还需要使用Reflection,请进行导入。

using System.Reflection;

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接