binding DataGridView to SortedBindingList bug

binding DataGridView to SortedBindingList bug

Old forum URL: forums.lhotka.net/forums/t/4991.aspx


AzStan posted on Wednesday, June 18, 2008

Recently I've had a new round of frustrations trying to display a master-details windows form.  I wanted the details grid to be sortable, so I wrapped my BusinessListBase-derived child collection in a SortedBindingList.  Lo and behold, the framework started throwing the dreaded "Edit level mismatch in CopyState" error. 

I reproduced the problem in the Project Tracker application, and believe there is definitely an undesirable interplay between the DataGridView and the SortedBindingList (maybe even a bug).  If you read on, I will tell you how to reproduce the behavior, and a possible workaround.

To reproduce the problem. 

1. Using the v3_5 project Tracker application, modify the BindUI() method in the ResourceEdit Winpart as follows:

Replace the following code:
      _resource.BeginEdit();
      this.ResourceBindingSource.DataSource = _resource;

with:
      _resource.BeginEdit();
      this.AssignmentsBindingSource.DataSource
 = new Csla.SortedBindingList<ProjectTracker.Library.ResourceAssignment>
 ( _resource.Assignments);
      this.ResourceBindingSource.DataSource = _resource;

2. Launch the app, and edit a resource.  When the resource edit form with the Assigned Project child grid appears, sort the child grid by clicking the column header of the 'Assigned' column.
3. Then, click the cancel button.  I get an 'edit level mismatch on CopyState' error.

On my own project, I am able to work around this problem by setting the grid's visible property to false before going through the unbind/rebind process.  This did not seem to work on the project tracker application.

I hope this helps move the effort forward, and I'd appreciate any insights or tips for sorting the contents of detail grids.

RockfordLhotka replied on Friday, June 20, 2008

Wow, that is an interesting issue!

I suspect that you'll need to set up the UI bindings different to start with. Rather than dragging the child grid out from the Data Sources window, you'll probably need to bind it as a standalone top level control - and then handle currency changes on the parent to bind the child to a new sortedbindinglist instance that wraps the new parent's child list.

What I think is happening here, is that the parent bindingsource thinks it is managing the child bindingsource - when in reality you've overridden the child binding. I doubt this is legal from the perspective of the bindingsource.

RockfordLhotka replied on Thursday, June 26, 2008

Any luck with my suggestion?

AzStan replied on Thursday, June 26, 2008

Rocky:

I tried separating the two binding sources, setting the ResourceAssignement binding source in a handler for the ResourceBindingSource.CurrentItemChanged event. The grid paints ok, but I still get an error when I sort it, then cancel.  So I looked a little further...

I've got three ResourceAssignment records showing.  I create an additional column to report editlevel of the underlying business objects.  Before sorting, the first row is at edit level 2, and the next two rows are at edit level 1.  The focus is on the first row.

Then, when I sort (on the Assigned date column), two rows (1 and 3) have an edit level of 2.  If I click cancel at this point, I begin the error sequence.  If on the other hand, I click on the last row before 'cancel', then there is only one row at edit level 2, and the error does not occur when I click cancel.

It seems that the grid is not calling EndEdit on the first grid row when the underlying object it moves out of the first position due to the application of the sort. 

I'm pretty busy right now, but I'll keep you posted as I learn more.

 

RockfordLhotka replied on Thursday, June 26, 2008

It is true that neither the grid nor bindingsource will call EndEdit in some cases. Specifically when dealing with grandchild collections, but I’m sure there are other cases too. To resolve that, you may have to handle the current item changed event from the bindingsource and force an EndEdit call – you can see this done in the parent-child-grandchild windows forms sample in svn.

 

Rocky

 

 

From: AzStan [mailto:cslanet@lhotka.net]
Sent: Thursday, June 26, 2008 5:40 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] binding DataGridView to SortedBindingList bug

 

Rocky:

I tried separating the two binding sources, setting the ResourceAssignement binding source in a handler for the ResourceBindingSource.CurrentItemChanged event. The grid paints ok, but I still get an error when I sort it, then cancel.  So I looked a little further...

I've got three ResourceAssignment records showing.  I create an additional column to report editlevel of the underlying business objects.  Before sorting, the first row is at edit level 2, and the next two rows are at edit level 1.  The focus is on the first row.

Then, when I sort (on the Assigned date column), two rows (1 and 3) have an edit level of 2.  If I click cancel at this point, I begin the error sequence.  If on the other hand, I click on the last row before 'cancel', then there is only one row at edit level 2, and the error does not occur when I click cancel.

It seems that the grid is not calling EndEdit on the first grid row when the underlying object it moves out of the first position due to the application of the sort. 

I'm pretty busy right now, but I'll keep you posted as I learn more.

 



Michael replied on Thursday, October 30, 2008

I have a very similar problem.

I have a BLB wrapped in a SortedBindingList, bound to one BindingSource on a UserControl with one editable DGV. Three rows: A, B, C with edit levels 2, 1, 1. Click the column header and the order and edit levels are: C2, B1, A2. Clicking Cancel does not cause the Edit level mismatch, but Save does when BeginEdit() is called.

After looking at the
parent-child-grandchild windows forms sample, I tried bindingSource.EndEdit() on CurrentChanged event. That eliminated part of the problem, but it's still reproducible as follows: three rows A, C, E with edit levels 1, 1, 1. Change A to D, select row C, then sort. Order and edit levels are: C2, D1, E1, and D is the selected row.

I have several screens inheriting the same logic, so I'll have to leave out the sorting for now, but help would be greatly appreciated.

Thanks
Michael

RockfordLhotka replied on Friday, October 31, 2008

Look at the RootChildGrandchildWinFormTest app

 

http://www.lhotka.net/cslacvs/viewvc.cgi/samples/trunk/CslaNet/cs/RootChildGrandchildWinFormTest/

 

This app is the core reference app for multi-level grid-based Windows Forms data binding.

 

Windows Forms data binding doesn’t leave much room for variation. You either do things the way they like, or it doesn’t work. This app works, and thus illustrates how they like it done.

 

Rocky

Michael replied on Sunday, November 16, 2008

Thanks for the reply, Rocky.

I had a look at the RootChildGrandchildWinFormTest, but it does not have a
SortedBindingList. When I wrapped the root.Children in a SortedBindingList<Child> in the Rebind method, I get the same EditLevelMismatch exception as above. Am I doing something wrong?

Mike

Michael replied on Tuesday, November 18, 2008

Has anyone else tried sorting the RootChildGrandchildWinFormTest?

Copyright (c) Marimer LLC