David Faulk
David Faulk

Reputation: 41

Displaying a large table of data

Disclaimer: My career has been in embedded software, and I've just recently gotten into desktop applications. The application I'm developing has a simulation that produces a sparse 2-D matrix that can be on the order of 3000x3000 elements. The sparse matrix object comes from a class we created in house. I have a requirement to display this sparse matrix in its expanded form to the user.

I initially expanded it into a DataTable and bound it to a DataGridView but had obstacles with the sum total of column FillWeights exceeding a limit. Even overcoming that, it takes several minutes of processing before anything is displayed in the table.

I came across the DataGridView's virtual mode. Virtual Mode seem very well suited for what I have, but there are still several issues:

  1. There doesn't seem to be a way to convey to the DataGridView the maximum number of rows and/or columns (for purposes of scaling the scroll bars). If I set .RowCount and/or .ColumnCount, the application hangs for 2 minutes for creating the columns.
  2. I lose column sorting in Virtual Mode. There seems to be some way to do it in the MSDN documentation, but it's not apparent.

This leads me to believe data in the GUI world isn't meant to be viewed in big unwieldy tables (specifically with thousands of columns), especially given that we've already got it in a sparse matrix form. I think I need to push back on the requirement.

What would you do in my situation?

Upvotes: 2

Views: 513

Answers (1)

Morris
Morris

Reputation: 156

Setting RowCount can take a long time if there are any columns whose AutoSizeMode is set to something other than None. If you need other settings, you could temporarily set them to none, then set RowCount, then set them to what you really wanted.

As for column sorting, you have to roll your own, but I found this easier than expected. You need a couple of fields recording which column (index) is currently sorted, and in which direction:

private int _currentSortedColumnIndex = -1; // No sorting at first
private SortOrder _sortOrder = SortOrder.None;

Then you need to set an event handler for ColumnHeaderMouseClick:

myDataGridView.ColumnHeaderMouseClick += MyDataGridView_ColumnHeaderMouseClick;

The event handler itself configures the sorted column to have the correct sort-glyph, and triggers a sort on your source data:

private void MyDataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    if (_currentSortedColumnIndex >= 0 && _currentSortedColumnIndex < myDataGridView.ColumnCount)
        mysDataGridView.Columns[_currentSortedColumnIndex].HeaderCell.SortGlyphDirection = SortOrder.None;

    if (_currentSortedColumnIndex == e.ColumnIndex)
        _sortOrder = _sortOrder == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
    else
    {
        _currentSortedColumnIndex = e.ColumnIndex;
        _sortOrder = SortOrder.Ascending;
    }

    mysDataGridView.Columns[_currentSortedColumnIndex].HeaderCell.SortGlyphDirection = _sortOrder;

    SortRecords(_currentSortedColumnIndex, _sortOrder);
    RefreshGrid();
}

SortRecords() is where you prepare your data cache so that your CellValueNeeded event handler can feed the cells in the new sort order, which is stored in _currentSortedColumnIndex and _sortOrder.

RefreshGrid() is where you basically clear the grid so that it will start firing CellValueNeeded events.

Upvotes: 0

Related Questions