Previously I asked a question about my dataGridView's performance due to it havign to display a large amount of rows that get added based on an incoming stream. Multiple solutions were given, one of them enabling virtual mode. MSDN has an article on the subject but it feels more complicated than what I need as it uses a database and an editable field. My DataGridView is only for displaying and the data I display is placed in a List.
After I accepted an answer I received this link: http://www.codeproject.com/Articles/23937/Paging-Data-with-DataGridView-in-VirtualMode . Even though that uses a database example, it's better suited for what I need. My List that will contain the data I want to display is declared as follows:
List<ResultRow> captureResults = new List<ResultRow>();
A ResultRow object is defined as follows:
/* 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. */
}
Following the article mentioned above, i created a ResultRowCache. The object is made as follows:
/* Page size set to 100. */
ResultRowCache _cache = new ResultRowCache(PAGE_SIZE, captureResults);
On my form Load event I do the following (related to this problem. I also added an event handler although that's done using the IDE so not directly showing in this code. Definition below!)):
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;
One thing I am wondering is how the RowCount is initialized here. It's probably 0 (due to the constructor call of ResultRowCache (see below)) but it never seems to get changed again. Does this assignment count as a reference? How does itupdate itself?
Anyway, onward with what I have, the ResultRowCache is defined as follows:
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;
}
}
}
Lastly, my CellValueNeeded event for the datagrid is defined as follows:
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 */
}
}
The problem: My datagrid remains empty even though the "captureResults" list gets filled. Here's what I tried so far:
- Update the RowCount member of the datagrid after the switch in the event.
- Declare the list with the total amount of results within the cache to ensure it's always up to date. (I was afraid "outside modifications" wouldn't go through to the List i passed in the cached constructor even though it was a reference. (Fairly new with C#))
- Set the RowCount of the datagrid to 100 (hard value) in the form's load event.
- Added an "Update()" call to the datagrid after adding something to the captureResults list. (this happens from a special thread which Invoke's a function that adds something to the list)
None of the above changed anything. The grid remains empty. I think I am missing something quite obvious here. Any suggestions?
-edit- Added something I tried to make it work.
See Question&Answers more detail:
os