C# DataGrid 重绘速度慢
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/842354/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
DataGrid slow to Redraw
提问by Eric Anastas
I'm using a System.Windows.Forms.DataGrid. It is populated with about 3000 rows and redraws very slowly. If I minimize and maximize my Form all the other controls just display but I end up watching the DataGrid redraw line by line. Everything in this DataGrid is readonly if that makes a difference.
我正在使用 System.Windows.Forms.DataGrid。它填充了大约 3000 行并且重绘非常缓慢。如果我最小化和最大化我的表单,所有其他控件都会显示,但我最终会一行一行地观看 DataGrid 重绘。如果这有所不同,则此 DataGrid 中的所有内容都是只读的。
Update:
更新:
I'm not really sure how to properly implement the CellValueNeeded() event for my project, or if it would help the performance of the DataGrid in my case.
我不确定如何为我的项目正确实现 CellValueNeeded() 事件,或者在我的情况下它是否有助于 DataGrid 的性能。
I'm creating a User Control that contains a DataGridView (see the code bellow). When the SetProject() method is called my control is set to a specific instance of my Project class. Then the control uses a static method Informa.Data.GetProjectDataTable(Project proj) to extract a DataTable from the Project. The DataSource property of the DataGrid is then set to the returned DataTable.
我正在创建一个包含 DataGridView 的用户控件(请参阅下面的代码)。当调用 SetProject() 方法时,我的控件被设置为我的 Project 类的特定实例。然后控件使用静态方法 Informa.Data.GetProjectDataTable(Project proj) 从 Project 中提取一个 DataTable。然后将 DataGrid 的 DataSource 属性设置为返回的 DataTable。
This is the first time I've done anything with ADO or DataGrids, so bear with me. It looks like CellValueNeed() allows me to override how a DataGrid finds a value for one of it's cells, but in my case this a lot more complicated then the examples on MSDN. The actual source of my data is a tree structure of various Node objects, the root of which is the Project instance. Each Node can have a variable set of properties, which can also be expanded by the user at runtime. Then there is a bunch of other complexities with Nodes inheriting property values from their parent nodes, and totaling other properties from their child nodes.
这是我第一次使用 ADO 或 DataGrids 做任何事情,所以请耐心等待。看起来 CellValueNeed() 允许我覆盖 DataGrid 如何为其中一个单元格找到值,但在我的情况下,这比 MSDN 上的示例复杂得多。我的数据的实际来源是各种 Node 对象的树结构,其根是 Project 实例。每个节点都可以有一组可变的属性,用户也可以在运行时扩展这些属性。然后还有一堆其他复杂性,节点从其父节点继承属性值,并从其子节点汇总其他属性。
Informa.Data.GetProjectDataTable() cuts through all this craziness and generates a single flat DataTable of all the properties of all the Nodes. At this point I don't care about being able to relate any change of this Table back to the original Tree structure, or updating specific parts of the table when the tree structure changes. All I want to do is display the data to the user in a DataGrid.
Informa.Data.GetProjectDataTable() 解决了所有这些疯狂问题,并生成了所有节点的所有属性的单个平面数据表。在这一点上,我不关心能够将此表的任何更改与原始树结构相关联,或者在树结构更改时更新表的特定部分。我想要做的就是在 DataGrid 中向用户显示数据。
So do I implement CellValueNeeded() to read from the DataTable provided by the Project? I would think a DataGrid would already know how to efficiency use a DataTable as a DataSource?
那么我是否实现了 CellValueNeeded() 来读取项目提供的 DataTable?我认为 DataGrid 已经知道如何高效地使用 DataTable 作为数据源?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Informa;
namespace Informa
{
public partial class ProjectGridControl : UserControl
{
private Project proj;
public ProjectGridControl()
{
InitializeComponent();
}
public void SetProject(Project proj)
{
this.proj = proj;
UpdateGridControl();
}
public void UpdateGridControl()
{
if (this.proj == null)
{
this.dataGrid.DataSource = null;
}
else
{
//Extracts a DataTable from the project and sets it as the
//DataSource of the property grid
this.dataGrid.DataSource = Informa.Data.GetProjectDataTable(proj);
}
}
}
}
}
采纳答案by rama-jka toti
Once there was a little Wolf named MacroSoft, that spend some time with Vidia the Sheep. They made slowest Text and Grid rendering on the planet and pushed all the work onto the CPU in boom year of hardware advance; all while the Sheep made sure to slow it down even further.
曾经有一只名叫 MacroSoft 的小狼,它和小羊 Vidia 一起度过了一段时间。他们制作了地球上最慢的文本和网格渲染,并在硬件进步的繁荣年将所有工作推到了 CPU 上;与此同时,绵羊确保进一步减慢速度。
If I'm right, you owe a letter to the lot :-)
如果我是对的,你欠这批人的一封信:-)
You are running NVidia card and their crappy drivers or similar as well as seeing MSFT refusing to fix up GDI+ to hardware accelerate along with friendly vendors (even Mono will have it done before they decide to give you some energy saving and proper hardware reuse; you know decent engineering ).
您正在运行 NVidia 卡及其蹩脚的驱动程序或类似程序,并且看到 MSFT 拒绝修复 GDI+ 以与友好的供应商一起进行硬件加速(即使 Mono 会在他们决定为您提供一些节能和适当的硬件重用之前完成它;您知道体面的工程)。
Wrap your DataGridView into a new type (ie. inherit ) and set its DoubleBuffered property to true, change the designer code to use that new type.
将您的 DataGridView 包装成一个新类型(即继承)并将其 DoubleBuffered 属性设置为 true,更改设计器代码以使用该新类型。
Visible "Line by line" rendering is how bad this industry is 2009/2010 with supercomputers on the desktop and single DLL a big company is refusing to fix but will gladly charge for having it execute even slower on Mounta-Dismounta-Vista. Jokers..
可见的“逐行”渲染是 2009/2010 年这个行业有多糟糕,桌面上有超级计算机和单个 DLL,一家大公司拒绝修复,但很乐意为它在 Mounta-Dismounta-Vista 上执行得更慢而收费。小丑..
回答by Reed Copsey
DataGridView should hanlde 3000 rows with no problems in Virtual Mode.
DataGridView 应该在虚拟模式下处理 3000 行没有问题。
Make sure to set VirtualModeto true (you mentioned you tried this), and also implement CellValueNeededproperly.
确保将VirtualMode设置为 true(您提到您尝试过此操作),并正确实现CellValueNeeded。
Read the MSDN Walkthrough on VirtualModefor details.
有关详细信息,请阅读有关 VirtualMode的MSDN 演练。
回答by Chris Doggett
Do you have auto-sizing for columns turned on? I've had users experience massive slowdown in our app with as few as 10 rows because auto-sizing was enabled. Basically, one grid allowed a user to check/uncheck a box to add a row to another grid, and the second grid would experience an exponential slowdown with each added row.
您是否打开了列的自动调整大小?由于启用了自动调整大小,我已经让用户在我们的应用程序中体验到只有 10 行的大幅减速。基本上,一个网格允许用户选中/取消选中一个框以将一行添加到另一个网格,而第二个网格会随着每添加一行而经历指数级减速。
After some profiling, I found it was taking ~12 seconds to add 5 rows to the second table. Finally tried turning off the auto-sizing of columns, and it's instantaneous now.
经过一些分析后,我发现将 5 行添加到第二个表需要大约 12 秒。最后尝试关闭列的自动调整大小,现在是即时的。
回答by Nick
I had big trouble with slow painting datagridview. I needed mine to be as large as possible on the screen, and it seemed the physical size of it had a much greater impact on pain speed than the amount of data, etc. What really did the trick for me was to set CellBorderStyle=None (apparently each cell is responsible for painting its own border, which seems ridiculous since the cell borders remain fixed on the screen so should be no need for every cell to constantly redraw its own borders as you scroll, but anyway...).
我在缓慢绘制 datagridview 时遇到了大麻烦。我需要我的在屏幕上尽可能大,而且它的物理尺寸对疼痛速度的影响似乎比数据量等要大得多。真正对我有用的是设置 CellBorderStyle=None (显然,每个单元格都负责绘制自己的边框,这看起来很荒谬,因为单元格边框在屏幕上保持固定,因此不需要每个单元格在滚动时不断重绘自己的边框,但无论如何......)。
Now, a grid without cell borders isn't really a good grid. But fortunately you can set DividerWidth for both columns and rows. Those values are defaulted to 0, but setting them to 1 (or higher if you want thicker) will give you back your "cell" borders identical in appearance to CellBorderStyle=Single, but this time painted "statically" (for lack of better word) for the entire datagridview.
现在,没有单元格边框的网格并不是真正的好网格。但幸运的是,您可以为列和行设置 DividerWidth。这些值默认为 0,但将它们设置为 1(或更高,如果您想要更厚)将使您的“单元格”边框在外观上与 CellBorderStyle=Single 相同,但这次是“静态”绘制的(因为缺少更好的词) ) 用于整个数据网格视图。
Also, set AutoResize properties to False if you have many rows.
此外,如果您有很多行,请将 AutoResize 属性设置为 False。
The improvement on paint speed was HUGE, at least in my case.
绘画速度的改进是巨大的,至少在我的情况下。
回答by Drew
In Visual Studio 2015 having the 2 DataGridView
AutoSize columns set to None yet having
在 Visual Studio 2015 中,将 2 个DataGridView
AutoSize 列设置为 None 还没有
dgv1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders;
was causing the issue of very slow row adds and user column resizing.
导致行添加非常慢和用户列调整大小的问题。
So if I REMout the above line, the UX is now fast. See AutoSizeRowsMode
and presumably the same issue with AutoSizeColumnsMode
因此,如果我将上面的代码REM,则 UX 现在很快。看到AutoSizeRowsMode
和大概相同的问题AutoSizeColumnsMode