以前我問了一個關於我的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