We have a grid, in virtual mode, and when we handle SaveCellInfo, we save the value into our internal object structure. There are certain combinations of cells that cannot be set, so it is possible for our objects to throw an exception, which we catch in our OnSaveCellInfo and display a message. If there was no exception, then we set e.Handled = True.
However, I've recently found (I think it used to work) that I'm getting an error "Specified argument was out of the range of valid values. Parameter name: rowIndex" from deep within the syncfusion code if I don't set e.Handled.
As an expirement, I took out all code that saves the data to our objects, I just handle the SaveCellInfo and do nothing in it, and I still get this error. Am I not doing something correctly? I just want to cancel out the user's changes if there is an error, and I don't know if there is an error until I'm ready to commit the values.
It seems to be working otherwise, so I'd settle for a way to catch and ignore this error.
ADAdministrator Syncfusion Team October 2, 2003 03:57 PM
I've been seeing the exact same problem. I had originally coded things by populating the grid manually. In OnSaveCellInfo we save values to a database via webservice which does extra checking. If the webservice returns an error, then I popup a message box. When we experienced performance issues, I switched to a Virtual Grid, which is working great except:
1) I was sometimes seeing this rowIndex out of range error when overriding OnSaveCellInfo. It was intermittent and seems to have gone away since I started setting e.Handled to true.
2) I call MessageBox.Show() if an error occurs during OnSaveCellInfo. This is now causing an endless loop somewhere deep within the grid call stack (in method EndUpdate) as it handles the WM_KILLFOCUS message. This worked perfectly before it was a virtual grid.
3) Tooltips fail to show up. In a nutshell, I'm overriding OnCellMouseHoverEnter and setting GridStyleInfo.CellTipText for the current cell. Nothing in that code has changed.
Anyway, I'd really like to know what is the "correct" way to handle an error during SaveCellInfo, and especially how I can best present that error to the user.
> We have a grid, in virtual mode, and when we handle SaveCellInfo, we save the value into our internal object structure. There are certain combinations of cells that cannot be set, so it is possible for our objects to throw an exception, which we catch in our OnSaveCellInfo and display a message. If there was no exception, then we set e.Handled = True.
> However, I've recently found (I think it used to work) that I'm getting an error "Specified argument was out of the range of valid values. Parameter name: rowIndex" from deep within the syncfusion code if I don't set e.Handled.
> As an expirement, I took out all code that saves the data to our objects, I just handle the SaveCellInfo and do nothing in it, and I still get this error. Am I not doing something correctly? I just want to cancel out the user's changes if there is an error, and I don't know if there is an error until I'm ready to commit the values.
> It seems to be working otherwise, so I'd settle for a way to catch and ignore this error.
ADAdministrator Syncfusion Team October 3, 2003 10:10 AM
SaveCellInfo is often called deep inside the grid logic when a lot is going on. The control was not really planned for showing up a message box inside SaveCellInfo.
Better is actually that you throw an exception from there and then handle it from whatever method which triggered the change.
For example in the grid if the current cell triggers a ChangeCell call (and thus SaveCellInfo was called) the grid will catch the exception and raise a CurrentCellConfirmChangesFailed. There you could safely display a message box.
With a databound grid when you leave the current row and SaveCellInfo throws an exception a ValidateFailed event is raised.
If the ChangeCells is triggered from some other code, it is usually your code that directly called ChangeCells (that is a direct call to ChangeCells or a change the style of a cell with grid[row,col].CellValue = x; or another property). In that case you can try/catch the exception.
But I think it should also be possible to display a message box from with SaveCellInfo. Within SaveCellInfo the problem you are facing is that most likely BeginUpdate has been called for the grid control. While in BeginUpdate mode the grid listens to the WndProc and holds back WM_PAINT messages until EndUpdate is called. This is the reason for the lockup/freeze.
To work around this problem call CancelUpdate() before displaying the message box. That should avoid the lock up/freeze.
ADAdministrator Syncfusion Team October 3, 2003 11:23 AM
But the whole point is that I'm getting the rowIndex out of range error even if I don't do anything; if I just _don't_ set e.Handled = true, without changing anything or displaying anything, or even one single line of code, I get that error. So the question has to be, what is the point of e.Handled? What is supposed to happen if it isn't set to true in SaveCellInfo?
ADAdministrator Syncfusion Team October 3, 2003 12:35 PM
If e.Handled is not set to true then the grid will move ahead with default processing of the event. That is it will then take the style object and assign it to its internal GridData object. That is done by a call such as
Data[rowIndex, colIndex].ModifyStyle(e.Style, modifyStyle);
So if you did not allocate a RowCount or ColCount before that is greater than rowIndex or colIndex passed in when calling ChangeCells then GridData will throw an exception that rowIndex is greater than RowCount or colIndex is greater than ColCount.
So, the following lines will throw an exception:
Grid.RowCount = 10;
Grid.ColCount = 10;
Grid[20, 20].CellValue = "lksjfdljkf";
but if you override SaveCellInfo and and you set e.Handled = true; then the grid will not do anything.
ADAdministrator Syncfusion Team October 3, 2003 03:27 PM
I just tested some more, and that does not appear to the issue. The RowCount is being set in QueryRowCount, and I checked in the SaveCellInfo event that it is set to the correct number of rows. The last thing called before the message function GridCurrentCell::MoveTo.
ADAdministrator Syncfusion Team October 3, 2003 03:36 PM
When you return the rowcount in QueryRowCount that does not mean that the grids internal GridData object has the same row count. That is only the value returned when you call grid.RowCount.
To check the row count allocated for the internal data object check grid.Data.RowCount. That count must be set by calling grid.Data.RowCount = numRows;
If you set grid.RowCount = numRows that will also set grid.Data.RowCount internally.
ANandreJanuary 20, 2004 03:03 PM
> For example in the grid if the current cell triggers a ChangeCell
> call (and thus SaveCellInfo was called) the grid will catch the
> exception and raise a CurrentCellConfirmChangesFailed. There you could
> safely display a message box.
I am throwing a custom Exception in SaveCellInfo handler. I also have a handler for CurrentCellConfirmChangesFailed. I notice the following behavior:
1) If I catch the exception in Current...Failed and call MessageBox.Show() then I experience the same weird behavior where the messagebox never shows up and the app is unresponsive. (note: Occasionally messagebox will work on the first try, but not usually, and never on subsequent tries). Break All in the debugger shows that it is in EndUpdate() inside CancelUpdate inside OnControlLostFocus.
2) If I do the same thing as in 1), except I call CancelUpdate() first, then it immediately locks up somewhere inside EndUpdate().
3) But if I do not catch the exception, then some code in the grid somewhere catches it and displays a messagebox, which does appear perfectly every time. This would be an acceptable solution, except that in my customer handler I do pre-processing of the exception in order to nicely format and display extra associated data: file, line #, etc.
So I wonder how to duplicate whatever the grid is doing so that I can display my message box...?
ADAdministrator Syncfusion Team January 20, 2004 04:04 PM
You can try setting your error message into the grid.CurrentCell.ErrorMessage property, and maybe the grid will display it for you at the proper time later in the current cell processing.
ANandreJanuary 20, 2004 04:59 PM
Good point. I''ll give that a try. However, I also have another situation where I need to popup a custom confirmation dialog with the user before the data is actually saved. I have tried this in both SaveCellInfo and CurrentCellValidating, with the same result in both. Opening it from SaveCellInfo worked before changing to the VirtualGrid code.
ANandreJanuary 20, 2004 06:02 PM
Okay, it turns out that the trick is to call EndUpdate() with the second parameter (fromModel) set to true. The value of the first parameter does not seem to matter. Once I did that, everything works like a charm.