If populating a grid takes too long, consider these techniques to speed things up. To improve performance:
Don't insert rows one at a time.
In many cases this is the primary reason that things seem to slow down after the insertion of many rows. If possible, before you call your code that fills cells, go ahead and call CGXGridCore::SetRowCount() with the total number of rows that you need.
Use the Data Object methods, e.g. CGXData::StoreValueRowCol(), to change the value of cells.
Don't call CGXGridCore::SetValueRange() to actually place the value in the grid. If you directly call CGXData::StoreValueRowCol() instead, this will bypass several pieces of grid code (CGXGridCore methods) that tend to affect performance. Using CGXData::StoreValueRowCol() can really speed things up. You would use a call something like this:
GetParam()->GetData()->StoreValueRowCol(...) |
Call CGXGridCore::LockUpdate(TRUE) to prevent redraws during multiple grid update calls.
Normally each command will update the grid (or invalidate the affected rectangle) immediately, which will result in substantially slowing down performance.
As you make a series of value changes, using LockUpdate() to prevent redraws will save significant time because subsequent commands need not invalidate the grid (and compute cell/window coordinates). If you have several subsequent commands that will change the grid, call LockUpdate(TRUE). After your series of commands, call LockUpdate(FALSE) and Redraw() to refresh the whole grid.
The following example illustrates how to use LockUpdate() while maintaining its original setting:
void CMyGridView::OnFormatResizecols( ) { // if no cells are selected,copy the current cell's // coordinates CGXRangeList selList; if (!CopyRangeList(selList, TRUE)) return; CGXLongOperation theOp; ResetCurrentCell( ); BeginTrans(GXGetAppData( )->strmResizeCols); // stop updating the display for subsequent commands BOOL bLockOld = LockUpdate(TRUE); TRY { // series of commands // (ResizeColWidthsToFit will do a lot of SetColWidth // commands) POSITION pos = selList.GetHeadPosition( ); while (pos) { if (!ResizeColWidthsToFit(selList.GetNext(pos))) AfxThrowUserException( ); } CommitTrans( ); } CATCH(CUserException, e) { Rollback( ); } END_CATCH // Now, refresh the whole grid LockUpdate(bLockOld); Redraw( ); } |
Don't generate Undo information while populating your grid.
As you populate your grid, Objective Grid may be generating and maintaining Undo information that will allow actions to be undone by the user. Generating and maintaining this Undo information can be time consuming. If you do not want your user to be able to undo the work you are doing to populate the grid, then you should disable the grid Undo mechanism. To do so, call GetParam()->EnableUndo(FALSE); before the code that populates the grid. If you want to enable the grid's Undo support after your grid has been populated, call GetParam()-> EnableUndo(TRUE); after it has been populated.
Set the grid to read-only.
Use CGXGridCore::SetReadOnly() and CGXGridParam::SetLockReadOnly() to manage the read-only status of the grid.
Use virtual mode with large data sets.
If you need to display a very large amount of data and find that populating the grid takes too long, instead of storing the data in the grid, consider using virtual mode for better performance. Virtual mode is ideally suited for displaying grids with many rows.
The great thing about virtual mode is that the grid only needs data for cells that are currently in view (not every row). This means that you supply values to the grid (from your data structure) only when the grid requests them. You do this by overriding GetStyleRowCol() and supplying the values there on demand. If this is a read-only grid, you would not have to override StoreStyleRowCol(), which is the second piece of a virtual grid.
Use GetStyleRowCol() instead of SetStyleRange(), as in this example:
BOOL CMyGridWnd::GetStyleRowCol(ROWCOL nRow, ROWCOL nCol, CGXStyle &style, GXModifyType mt, int nType) { BOOL ret= CGXGridCore::GetStyleRowCol( nRow, nCol, style, mt, nType); if(nType >= 0) { if (nCol>1&&nRow>1&&nCol<367&&nRow<151) { style.SetValue(value); style.SetInterior(color); } } return ret; } |
Take a look at the VirtGrid tutorial that ships with Objective Grid to see how you might use virtual mode. Refer to Section 5.9, "Virtual Grids," and Chapter 10, "VirtGrid Tutorial," for more information on Virtual Grids.
Keep code out of GetRowCount() and GetColCount().
GetRowCount() and GetColCount() are used extensively to validate values within routines. In addition, because HitTest() is called repeatedly on every mouse move and because this method touches a lot of grid code, including GetRowCount(), it is not unusual for GetRowCount() to be called thousands of times in a short period of time. Because GetRowCount() and GetColCount() are called quite often, your overrides of these methods are not an appropriate place to do extensive calculation.
See Section 5.5.3 for more information on Hit-Testing.
Copyright © Rogue Wave Software, Inc. All Rights Reserved.
The Rogue Wave name and logo, and Stingray, are registered trademarks of Rogue Wave Software. All other trademarks are the property of their respective owners.
Provide feedback to Rogue Wave about its documentation.