Edit Level mismatch error

Edit Level mismatch error

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


fredg posted on Friday, January 20, 2012

Hi,

     We are coding against windows form. Our root object contains multiple children objects. When updating a child opject, Edit Level mismatch error happens.

     I check the Edit Level of every object (including parent, children's) and if one of the chilren has different edit level from others', that means this particular child has problem even if we're updating another child object?

 Thanks.

RockfordLhotka replied on Friday, January 20, 2012

Windows Forms data binding is very particular about following its rules. And so is CSLA. The rules are relatively straightforward, but you can't deviate.

The primary rule: every beginedit must have a corresponding canceledit/endedit on each object (parent, child, etc).

Edit level mismatch occurs because some object in the object graph didn't get a canceledit/endedit call. The most common reason is that the object wasn't properly unbound from the UI prior to saving.

The Using CSLA .NET 3.0 ebook has pretty extensive coverage of Windows Forms data binding and how to make it work correctly.

fredg replied on Friday, January 20, 2012

Thanks. Can I have more specific for my situation:

The parent object has 2 children objects: when updating child 1, the mismatch error happens. The parent and child1 have edit level 0, child2 has edit level 1. That necessarily means child 2 has problem? We need to determine which one has issue and fix that object.

RockfordLhotka replied on Friday, January 20, 2012

There is no real easy way to find the object that has the elevated edit level. Nor can you "fix that object". You'll have to fix the broken UI code that isn't using data binding correctly.

The thing to keep in mind is that data binding uses a concept called currency. In any given binding source only one object is current. That object will have an elevated edit level.

In a detail form bound to a single object, that object clearly has currency.

In a datagrid or other complex binding control that is bound to a list, only one object in the list will have currency. As the user moves from row to row currency is automatically moved/managed by the WinForms binding source object.

With parent-child objects, the most common scenario is that the parent object is bound to a form, so it has currency.

Then the child collection is bound to a datagrid or something like that. So one child has currency too (because this is a separate binding source).

Before you can save, you must first unbind the child collection properly. And that usually means manually calling EndEdit on the current row, because data binding won't do that automatically :(

Then you must unbind the parent object and ensure EndEdit is called.

Then you can save the object.

Then you rebind the UI to the result of the Save method.

Again, this is covered in some detail in the 3.0 ebook. In CSLA .NET 3.7 and higher there are also some helper components in Csla.Windows that automate some of this work. Those components are discussed briefly in the Expert 2008 Business Objects book.

JonnyBee replied on Saturday, January 21, 2012

Hi,

You can also download the latest source from CslaContrib and look at the CslaContrib.Windows.BindingHelperExtension class.

There is some hard learned lessons in that code for Rebind/Unbind data objects and BindingSource.

 

fredg replied on Tuesday, January 24, 2012

Sorry I cannot find CslaContrib.Windows.BindingHelperExtension class in CslaContrib.

JonnyBee replied on Tuesday, January 24, 2012

Hi,

Download the latest source code from here:
http://cslacontrib.codeplex.com/SourceControl/list/changesets

or use this direct link to BindingSourceExtensions.cs:
http://cslacontrib.codeplex.com/SourceControl/changeset/view/92754#1623433

 

 

fredg replied on Thursday, January 26, 2012

Thanks. In the ProjectEdit control sample, the parent is bound to a form, and the child collection is bound to a datagrid. So the RebindUI() looks like: 

private void RebindUI(bool saveObject, bool rebind)
{   
  this.projectBindingSource.RaiseListChangedEvents = false;
  this.resourcesBindingSource.RaiseListChangedEvents = false;
  try
  {    
   UnbindBindingSource(this.resourcesBindingSource, saveObject, false);
   UnbindBindingSource(this.projectBindingSource, saveObject, true);
       .............
  }
}

   My question is: if the UI only contains a datagrid which is bound to child collection and parent object is NOT bound to any control/form, can we reduce the above code to the following and do NOT need to care about parent bindingsource?

 private void RebindUI(bool saveObject, bool rebind)  
 {
 this.resourcesBindingSource.RaiseListChangedEvents = false;
 try
 {
   UnbindBindingSource(this.resourcesBindingSource, saveObject, false);
      ......
 }
}

        

 

Copyright (c) Marimer LLC