Reputation: 335
I have an existing application that implements a DataGridView. The DataGridView is referenced extensively, adding rows (from an xml file), changing row visibility, changing column visibility, adding colour/formatting to particular cells, custom sorting etc, as well as many foreach and Parallel.foreach iterations across the row collection, selected cells, selected rows etc.
It all works fine, but the DataGridView struggles with very large numbers of rows. I've been trying to find a way of improving performance without having to rewrite the entire app. Ideally, I want to create a derived class which improves performance, and then all I'd need to do is reference the derived class (instead of the DataGridView class) when creating the table object in the designer.
I've read up on VirtualMode, but also this: Does the Windows Forms DataGridView implement a true virtual mode?, which suggests that VirtualMode is only really a hybrid virtual mode. I wrote the proof-of-concept below (it needs a lot of work!), but it doesn't seem to improve performance at all. I've formed the view that the approach is flawed in principle, because in effect the DataGridView is still loading all the rows. I can't immediately see an easy way around that, because the foreach statements elsewhere in the code still need to "see" the entire set of data, and other attributes of the rows (e.g. colour, font etc) would still need to exist for each row.
Before I abandon it altogether, is what I'm trying to do achievable in this way?
Proof of concept code (that makes no different to performance):
public class CachedEditableDataGridView : DataGridView
{
List<object[]> cache = new List<object[]>();
public CachedEditableDataGridView()
{
VirtualMode = true;
this.RowsAdded += new DataGridViewRowsAddedEventHandler(CachedEditableDataGridView_RowsAdded);
this.RowsRemoved += new DataGridViewRowsRemovedEventHandler(CachedEditableDataGridView_RowsRemoved);
this.CellValueNeeded += new DataGridViewCellValueEventHandler(CachedEditableDataGridView_CellValueNeeded);
this.CellValuePushed += new DataGridViewCellValueEventHandler(CachedEditableDataGridView_CellValuePushed);
}
private void CachedEditableDataGridView_RowsAdded(object sender,
DataGridViewRowsAddedEventArgs e)
{
object[] obj = new object[this.Columns.Count];
cache.Add(obj);
this.RowCount = cache.Count;
}
private void CachedEditableDataGridView_RowsRemoved(object sender,
DataGridViewRowsRemovedEventArgs e)
{
cache.RemoveAt(e.RowIndex);
this.RowCount = cache.Count;
}
private void CachedEditableDataGridView_CellValueNeeded(object sender,
DataGridViewCellValueEventArgs e)
{
if (cache.Count == 0)
{
e.Value = String.Empty;
}
else
{
e.Value = cache[e.RowIndex][e.ColumnIndex];
}
}
private void CachedEditableDataGridView_CellValuePushed(object sender,
DataGridViewCellValueEventArgs e)
{
cache[e.RowIndex][e.ColumnIndex] = e.Value;
}
}
Upvotes: 0
Views: 43