以前我问了一个关于我的dataGridView的性能的问题,因为它显示大量的基于传入流添加的行。给出了多个解决方案,其中一个启用虚拟模式。 MSDN有一篇关于这个主题的文章,但它感觉比我需要的更复杂,因为它使用数据库和可编辑字段。我的DataGridView仅用于显示,我显示的数据放置在List中。DataGridView虚拟模式与一个简单的列表作为源
在我接受答案后,我收到此链接:http://www.codeproject.com/Articles/23937/Paging-Data-with-DataGridView-in-VirtualMode。尽管它使用数据库示例,但它更适合我所需。我的列表将包含我想要显示如下声明的数据:
List<ResultRow> captureResults = new List<ResultRow>();
一个ResultRow对象的定义如下:
/* Simplified */
public class ResultRow
{
private int first = 0;
private string second = "";
private UInt64 third = 0;
private IPAddress fourth = null;
/* etc */
public ResultRow()
{
}
public void Set (<the values>) //In actuallity a KeyValuePair
{
//field gets set here
}
public UInt64 Third
{
get { return third; }
set { third = value; }
}
/* etc. */
}
继文章上面提到的,我创建了一个ResultRowCache。对象是由如下:。
/* Page size set to 100. */
ResultRowCache _cache = new ResultRowCache(PAGE_SIZE, captureResults);
在我的窗体的Load事件中,我做了以下(与此相关的问题,我还添加了一个事件处理程序,尽管这是一个使用IDE,无法直接显示在此代码做了定义)):
dataGrid.VirtualMode = true;
_cache = new ResultRowCache(PAGE_SIZE, captureResults);
dataGrid.Columns.Add("FirstColumn" , "First column header");
dataGrid.Columns.Add("Second Column", "Second column header");
/* Etc. Adding all columns. (Every member or ResultRow has it's own column. */
dataGrid.RowCount = (int)_cache.TotalCount;
我想知道的一件事是RowCount是如何在这里初始化的。它可能是0(由于ResultRowCache的构造函数调用(见下文)),但似乎从未再次发生变化。这项任务是否算作参考?它如何更新?
反正以后与我有什么,该ResultRowCache定义如下:
public class ResultRowCache
{
public int PageSize = 100;
public long TotalCount;
public List<ResultRow> CachedData = null;
private List<ResultRow> FullData;
int _lastRowIndex = -1;
public ResultRowCache (int pageSize, List<ResultRow> total)
{
PageSize = pageSize;
FullData = total;
LoadPage(0);
}
public void LoadPage (int rowIndex)
{
int lastRowIndex = rowIndex - (rowIndex % PageSize);
/* Page already loaded */
if(lastRowIndex == _lastRowIndex) return;
/* New page */
_lastRowIndex = lastRowIndex;
/* Create a new cashes data object */
if(CachedData == null) CachedData = new List<ResultRow>();
/* If cached data already existed, clear */
CachedData.Clear();
/* The index is valid (there is data */
if (lastRowIndex < FullData.Count)
{
/* Not a full page */
if (lastRowIndex + PageSize > FullData.Count)
{
CachedData = FullData.GetRange(lastRowIndex, ((lastRowIndex + PageSize) - 1) - FullData.Count);
}
/* Full page */
else
{
CachedData = FullData.GetRange(lastRowIndex, PageSize);
}
}
TotalCount = CachedData.Count;
}
}
}
最后,我为DataGrid CellValueNeeded事件的定义如下:
void DataGridCellValueNeededEvent(object sender, DataGridViewCellValueEventArgs e)
{
_cache.LoadPage(e.RowIndex);
int rowIndex = e.RowIndex % _cache.PageSize;
switch (dataGrid.Columns[e.ColumnIndex].Name)
{
/* Not actual names, example */
case "FirstColumn": e.Value = _cache.CachedData[rowIndex].First; break;
case "SecondColumn": e.Value = _cache.CachedData[rowIndex].Second; break;
/* Rest of the possibly columns/ResultRow values */
}
}
的问题:我的即使“captureResults”列表被填充,datagrid仍为空。这是我到目前为止所尝试的:
- 更新事件中切换后的datagrid的RowCount成员。
- 用缓存中的结果总数声明该列表,以确保它始终处于最新状态。 (我担心“外部修改”不会通过缓存的构造函数传递给我的列表,尽管它是一个参考。(与C#相同)
- 将datagrid的RowCount设置为100(硬值)在窗体的加载事件中。
- 在向CaptureResults列表添加内容后,向datagrid添加了“Update()”调用。 (这发生在一个特殊的线程中,这个调用的功能会添加一些东西到列表中)
以上都没有改变任何东西。网格保持空白。我想我错过了一些很明显的东西。有什么建议么?
-edit-增加了一些我试图让它工作的东西。
我设法让它在没有缓存的情况下工作,通过在每次添加后更新RowCount并使用我的列表大小。然而性能似乎更糟糕。 (也许是因为我每次增加更新表单,而不是后台工作人员每隔 ms)我的应用程序在处理完数据后也会相对快速地冻结。这是虚拟模式的错误实现还是其他问题? (因为某些原因,绘制行(可以有不同的背景颜色)对于这个系统来说是非常困难的。我的笔记本电脑(功能更强大)可以更轻松地完成这项任务。 –
Arnold4107176
您是如何在每次添加后更新RowCount的?分享这段代码,因为我不确定它是如何工作的,而且听起来不太正确。如果将列表分配给bindingSource,然后将其分配给Grid.DataSource,那么应该充分跟踪rowCounts和内部列表。 –
啊,我认为这是我对概念缺乏理解的结果,当我启用虚拟模式时,我没有为DataGridView设置数据源,因为我认为这是性能问题,如果我保持这种唯一区别是我将VirtualMode属性设置为true,并且定义了CellValueNeeded事件,这是否正确?我不太明白为什么这会消除你将会得到的性能。对大型集合来说效率低下的事件的默认实现?用虚拟模式关闭它可能不起作用,我必须阅读。 – Arnold4107176