When this form is loaded, the collection class' static method will read the data from the database and return a collection instance. If some data objects are loaded into the collection, everything is ok and the BindingSource's AddingNew event will not be fired automatically. If no data object is loaded into the collection, then the BindingSource's AddingNew event will be fired automatically. And then my code will load a second form to edit a new data object.
Then I just simply close the second form without saving the new data object. The execution returns to the list form, and re-bind the BindingSource with a new collection returned from the collection's static method. Since no data object is added, the collection is still emtpy. And an exception is thrown: System.InvalidOperationException: Operation is not valid because it results in a reentrant call to the SetCurrentCellAddressCore function.
Why is it ok when the collection is not empty but causing an exception when the collection is empty Maybe my re-binding is wrong BTW, at design time, I bind the BindingSource with the MyCollectionClass type.
My code snippet is attached below.
private void MyListForm_Load(object sender, EventArgs e) { BindData(); } private void myBindingSource_AddingNew(object sender, AddingNewEventArgs e) { // load edit form to edit a new data object RefreshBinding(); } private void BindData() { myCollection = MyCollectionClass.GetData(); // returns a MyCollectionClass instance with 0 or more data objects, so every time this is a new instance myBindingSource.DataSource = myCollection; // exception occurs here after returning from edit form with an emtpy collection } private void RefreshBinding() { BindData(); //myBindingSource.ResetBindings(false); // should I call this } |
Thanks!

BindingSource's AddNew fired automatically if no object in collection
Srreh
I am receiving the same issue, but I am not using binding. Here is my scenario; I have a datagridview that accepts user input. On the CellEndEdit, the underlying dataset (unbound) is updated. At this point an event is raised to update the UI. This process clears the data grid and reloads. The dgv.Rows.Clear(), throws the exception. Now this does not happen on all columns, just the combo and checkbox columns.< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Any advice would be greatly appreciated,
Darell F. Butch Jr.
Muljadi Budiman
I finally received an answer to my bug submission about this: it appears that it is 'by design':
(you need to sign in to view the answer)
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx FeedbackID=119366&wa=wsignin1.0
So that's that
garyniemi
markomar
The problem arises when the rowindex and columnindex are equal. I've only tested this on values of 2 and 3, tho.
Brian Stringham
Joe McGrath
I'm putting a combobox into a cell (which starts off as a text cell) when cell receives focus, and changing the cell back to a text cell again (with the value selected) when it loses focus.
It all works fine until the rowindex and columnindex are both 2 - I haven't tried it with other values, so it may be that when they're equal, the problem arises.
The exception message is "Operation is not valid because it results in a reentrant call to the SetCurrentCellAddressCore".
Any help would be greatly appreciated.
ifoko
class FixReEntrantDataGridView : DataGridView
{
public bool reEntrent = false;
protected override bool SetCurrentCellAddressCore(int columnIndex, int rowIndex, bool setAnchorCellAddress, bool validateCurrentCell, bool throughMouseClick)
{
bool rv = true;
if (!reEntrent)
{
rv = base.SetCurrentCellAddressCore(columnIndex, rowIndex, setAnchorCellAddress, validateCurrentCell, throughMouseClick);
}
return rv;
}
}
and then when changing the cell from combo box to text box and visa-versa.
this.myDataGrid.reEntrent = true;
this.myDataGrid.Rows[e.RowIndex].Cells[e.ColumnIndex] = dgvt;
this.myDataGrid.reEntrent = false;
It works and it still protects the SetCurrentCellAddressCore from getting called at the wrong times.
Charlie_MS
I have a very similar problem.
The DataGridView consists of only two ComboBoxColumns
As the form loads I bind the DataGridView.DataSource to a DataTable.
Next the user clicks the "Add" button and I set as it follows:
DataGridView.AllowUserToAddRows =
true;DataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnEnter;
If news values are selected, the changes are saved and I set the DataGridView state back to normal:
DataGridView.AllowUserToAddRows = false;
DataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammactically;
If no new values are selected, no action is taken and I set the DataGridView state back to normal and here is where the problem happens:
DataGridView.AllowUserToAddRows = false;
generates the exception in discussion: "Operation is not valid because it results in a reentrant call to the SetCurrentCellAddressCore".
Any help Please =(
jyotish
Pvanroos
No, I did not get an actual answer. I got the work around, which was posted above. We are currently using another control and have not transitioned back to the DataGridView. Also, we have upgraded to latest version which I believe has fixed the problem, but have not tried it. If you would like me to do that, I could and give you the results.
miraz912
We had a similar problem where once the grid was updated we wanted to refresh the grid. I was getting the error. It appears that att he point that I want to refresh the grid (in the RowEnter) the handle on the grid is on a different thread.
Instead I had to call the function using a
Dim
refreshDelegate As New MethodInvoker(AddressOf RefreshGrid)refreshDelegate.BeginInvoke(
Nothing, Nothing)and in my RefreshGrid function I had to test to see if the InvokeRequired was false before running the code to refresh the data.
If
InputOutputGrid.Grid.InvokeRequired ThenDim
callBack As New SetGridCallBack(AddressOf RefreshGrid)Me
.Invoke(callBack, Nothing) Else........ code to update the grid.
Hope this helps
lindi_xp
Got it fixed, but it still causes a slight annoyance. The current cell changes on cell leave. But sinces its for that only cell, I can live with it.
class FixReEntrantDataGridView : DataGridView
{
private bool reEntrent = false;
protected override bool SetCurrentCellAddressCore(int columnIndex, int rowIndex, bool setAnchorCellAddress, bool validateCurrentCell, bool throughMouseClick)
{
bool rv = true;
if (!reEntrent)
{
reEntrent = true;
rv = base.SetCurrentCellAddressCore(columnIndex, rowIndex, setAnchorCellAddress, validateCurrentCell, throughMouseClick);
reEntrent = false;
}
return rv;
}
}
Mike12345
You may be able to work around this by setting AllowUserToAddRows to false before calling RefreshBindings() and then set it to true after you've called RefreshBindings().
In general, I'd recommend against re-binding in AddingNew. AddNew will create an instance of your type (if possible) and add it to your list. The way this was architected to work was that if your list was empty, AddNew (AddingNew) would get called. In AddingNew you should create a new instance of your type, possibly set default values, and then set e.NewObject to the new instance. In your case, you're re-binding in AddingNew and not creating a new instance (which BindingSource will then do for you) which may cause additional problems.
The design pattern is:
Bind you Grid to the BindingSource
Bind your DataSource (list) to the BindingSource
If you DataSource is Empty, AddNew will get called (which fires AddingNew)
In AddingNew set e.NewObject to a new instance of your Type
BindingSource will then add this new instance to the DataSource (list)
Joe Stegman
The Windows Forms Team
Microsoft Corp.
This posting is provided "AS IS" with no warranties, and confers no rights.
SammyLim
Thanks for posting the code bellow. It help me to solve my problem:
class FixReEntrantDataGridView : DataGridView
{
private bool reEntrent = false;
protected override bool SetCurrentCellAddressCore(int columnIndex, int rowIndex, bool setAnchorCellAddress, bool validateCurrentCell, bool throughMouseClick)
{
bool rv = true;
if (!reEntrent)
{
reEntrent = true;
rv = base.SetCurrentCellAddressCore(columnIndex, rowIndex, setAnchorCellAddress, validateCurrentCell, throughMouseClick);
reEntrent = false;
}
return rv;
}
}