之前我提出了一个关于dataGridView性能的问题,因为它需要显示大量基于传入流添加的行。多个解决方案被给出,其中之一是启用虚拟模式。MSDN有一篇关于这个主题的文章,但它感觉比我需要的更复杂,因为它使用了一个可编辑字段的数据库。我的DataGridView仅用于显示,并且我要显示的数据存放在List中。
在我接受了一个答案后,我收到了这个链接:http://www.codeproject.com/Articles/23937/Paging-Data-with-DataGridView-in-VirtualMode。即使那个例子使用了数据库,它更适合我所需要的。将包含我要显示数据的List声明如下:
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);
在我的表单加载事件中,我执行以下操作(与此问题相关。我还添加了事件处理程序,尽管这是使用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在这里是如何初始化的。由于ResultRowCache的构造函数调用,它可能是0,但似乎从未再次更改。这个分配算是引用吗?它是如何自我更新的?
无论如何,接下来介绍一下我所拥有的,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”列表被填充。以下是我尝试过的内容:
- 在事件中的开关后更新数据网格的RowCount成员。
- 使用缓存中总结果数声明列表,以确保它始终是最新的。(我担心即使它是引用传递的,也不能通过缓存构造函数传递的List进行“外部修改”。(对C#还很陌生))
- 在表单的加载事件中将datagrid的RowCount设置为100(硬编码)。
- 在向“captureResults”列表添加内容之后,将“Update()”调用添加到数据网格中。(这发生在一个特殊线程中,该线程Invoke一个向列表添加内容的函数)
以上任何一项都没有改变任何东西。网格仍然为空。我觉得我在这里漏了一些非常明显的东西。有什么建议吗?
-编辑- 添加了一些我尝试让它工作的内容。