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.
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.
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.
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.
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
Copyright (c) Marimer LLC