CancelEdit only works for the previous state when bound to a data grid view

CancelEdit only works for the previous state when bound to a data grid view

Old forum URL:

ErikJL posted on Thursday, January 07, 2010

I'm using 2.1.4 and am prototyping our first "real" business object. In testing the N-level undo capability, I call BeginEdit() onn a business object, modify a field, and do this a second time so the edit level is at 2. My understanding is that a CancelEdit() call will restore the property to its previous edit level state (1 in this case), and this works fine. When I call CancelEdit() a second time to restore the object to it's edit level 0 state, the edit level indeed goes to 0 but the property is not restored to its edit level 0 value. (It doesn't matter if I go to 10 edit levels, the value will only go back to the previous edit level value.)

Stepping through UndoableBase reveals that CopyState() is being called automatically after I call UndoChanges() via CancelEdit(). Suspecting some shenanigans from the data grid view, I remove the business list as its data source, and tada, everything works fine.

So my question is what the heck is going on with the data grid view, and how do I deal with this problem?



JonnyBee replied on Friday, January 08, 2010

Hi Erik,

Do you call BeginEdit/CancelEdit while databinding is active?

I believe that is not supported - you should never call BeginEdit/CancelEdit when databinding is active as this is called very frequently from databinding itself and databinding expects to have full control on the objects involved.

ajj3085 replied on Friday, January 08, 2010


If possible, I would recommend upgrading to 3.0.5.  There are a bunch of bug fixes and other enhancements.  3.0.5 works fine on .Net 2.0 as well, so don't let the versioning confuse you.  I think some of the bug fixes revolve around data binding as well; check out the change logs for more details.



RockfordLhotka replied on Friday, January 08, 2010

It is at the 3.0 point when I added the checks for mis-matched edit levels - so be aware than moving to 3.0.5 may reveal UI bugs. That can be frustrating, but if you get edit level mismatch exceptions they indicate UI coding bugs that were essentially undetectable until 3.0.x...

ErikJL replied on Monday, January 11, 2010

Johnny: I was indeed calling BeginEdit and CancelEdit while data binding is active. I'm assuming I need to remove the binding, perform the method call, and then re-bind? Or am I supposed to let the grid view control manage those calls? (I'm an electrical engineer posing as a software engineer so please forgive my ignorance on what most developers probably already know.)

I will upgrade to 3.0.5 as suggested. As our company is not using .NET 3.5 yet, I am stuck with .NET 2.0 for now.

ajj3085 replied on Monday, January 11, 2010

The typical usage is that you like the grid or other controls handle it.  Is there some kind of form level undo button in play here?  That's the most likely reason you'd want to do BeginEdit / CancelEdit on your own.

But to answer you question directly, yes, you need to unbind, do your calls, then rebind. 

If, after your Csla upgrade, you start getting exceptions about mismatched edit levels, that means the binding isn't being done correctly.  You'll have to fix those, and probably the easiest way if you can is to use BindingSourceNode.  That component (included with Csla) has made my life so much easier.

DaleStan replied on Monday, January 11, 2010

But to answer you question directly, yes, you need to unbind, do your calls, then rebind.
Could I convince you to elaborate, please?
I am binding by assigning a SortedBindingList (of CSLA business objects), to the DataGridView's DataSource but neither of
dv.DataSource = null;
will unbind the list from the DataGridView, as evidenced (I believe) by CancelEdit failing to revert to any state other than that at the most recent call to BeginEdit, and by CancelEdit failing to decrement the EditLevel of the contained objects, whether I call BeginEdit/CancelEdit on the container or the on the contained objects.

Google suggested that I use dvReportTemplates.BindData() to unbind, but that method doesn't exist, and I saw nothing in the members of either DataGridView or SortedBindingList that looks promising.

ajj3085 replied on Monday, January 11, 2010

I think something along these lines is what you need to do:

Set RaiseListChangedEvents to false for all bindingsource components

Call EndEdit on all bindingsource components (order matters!)

Set their DataSource properties to null.

Call your methods

Rebind, re-enable RaiseListChangedEvents

You're not touching the grid or anything else, just the bindingsoure components, and its NOT just the child item bindingsource, its all of them.

DaleStan replied on Monday, January 18, 2010

Thank you. Setting RaiseListChangedEvents to false is the part I was missing. Everything seems to work now.

ErikJL replied on Monday, January 11, 2010

Yout are correct - I have dedicated buttons that were just calling BeginEdit and CancelEdit so I could see and learn how the functionality works. We will be using these business objects in automated procceses as well so I had to know how to utilize the n-level undo manually.

I installed 3.0.5 and so far so good, no binding errors that I can see.

Thanks for your help everyone!

Copyright (c) Marimer LLC