DataGridView虚拟模式以简单列表作为源

之前我问过一个关于我的dataGridView性能的问题,因为它显示了大量的行,这些行是根据传入的流添加的。 给出了多个解决方案,其中一个解决方案启用虚拟模式 MSDN有一篇关于这个主题的文章,但它比我使用数据库和可编辑字段所需要的更复杂。 我的DataGridView仅用于显示,我显示的数据放在List中。

在我接受答案后,我收到了这个链接: http : //www.codeproject.com/Articles/23937/PagingANN-with havenGridView-in-VirtualMode 。 即使它使用数据库示例,它也更适合我需要的东西。 包含我要显示的数据的My List声明如下:

List captureResults = new List(); 

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 () //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。 它可能是0(由于ResultRowCache的构造函数调用(见下文))但它似乎永远不会再次更改。 这项任务是否算作参考? 它如何改变自己?

无论如何,继续我所拥有的,ResultRowCache定义如下:

 public class ResultRowCache { public int PageSize = 100; public long TotalCount; public List CachedData = null; private List FullData; int _lastRowIndex = -1; public ResultRowCache (int pageSize, List 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(); /* If cached data already existed, clear */ CachedData.Clear(); /* The index is valid (there is data */ if (lastRowIndex  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的RowCount成员。
  • 使用缓存中的结果总数声明列表,以确保它始终是最新的。 (我担心“外部修改”不会进入我在缓存构造函数中传递的List,即使它是一个引用。(相当新的C#))
  • 在表单的load事件中将datagrid的RowCount设置为100(硬值)。
  • 在向captureResults列表添加内容后,向datagrid添加了“Update()”调用。 (这发生在一个特殊的线程中,Invoke是一个向列表中添加内容的函数)

以上都没有改变任何东西。 网格仍然是空的。 我想我错过了一些非常明显的东西。 有什么建议?

-edit-添加了我试图让它工作的东西。

我觉得使用Cache会使这个过程有些复杂化(虽然在向你发送以这种方式实现的msdn链接之后我确实感到有责任)。

我建议作为一个起点是:

  1. 丢弃缓存(如果你遇到内存问题,这可能会很有用,但是现在让你的数据网格填充)

  2. List存储在实例变量中。

  3. 确保dataGrid.VirtualMode = true; (或等同)

  4. 实现CellValueNeeded如下:

      private void gridContacts_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) { ResultRow dataObject = resultRows[e.RowIndex]; switch(e.ColumnIndex) { case 0: e.Value = dataObject.First; break; case 1 : e.Value = dataObject.Second; break; //etc.. } } 

注意:您需要在DataObject中公开一些额外的公共属性,以便可以将它们设置为方法中的值。

看看你如何继续下去。 如果在CellValueNeeded方法中设置了一些断点,这些断点应该有助于调试任何进一步的意外行为。 祝好运。