Edit level problem with root/child/grandchild

Edit level problem with root/child/grandchild

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


Michael posted on Tuesday, November 17, 2009

Hi everyone

I am familiar with the root/child/grandchild example. Apologies for the long post, but this is driving me crazy.

I have the following object hierarchy:
- HeaterBank BB
 - Stages BLB
  - Stage BB
   - Elements BLB
    - Element BB

I show a dialog to edit the HeaterBank, do nothing and click Cancel. Immediately, I edit the same HeaterBank which creates a new Form, do nothing and click Cancel. This throws "Edit level mismatch in UndoChanges."

To simplify the testing, I'm not binding the HeaterBank, just calling BeginEdit() on it and binding Stages as a root BindingSource, and Elements to a BindingSource with
DataSource = bindStages with DataMember = Elements. I have tried with and without calling bindElements.EndEdit() on bindStages_CurrentChanged. The following shows the edit levels at various points, with the error shown in red.

Before HeaterBank.BeginEdit()
Heater bank: 0
  Stage: 0
    Element: 0

After HeaterBank.BeginEdit()
Heater bank: 1
  Stage: 1
    Element: 1

After bind Stages
Heater bank: 1
  Stage: 2
    Element: 2

Cancel clicked

Before unbind Elements
Heater bank: 1
  Stage: 2
    Element: 2

Elements unbound, before unbind Stages
Heater bank: 1
  Stage: 2
    Element: 1

Stages unbound, before HeaterBank.CancelEdit()
Heater bank: 1
  Stage: 1
    Element: 1

After HeaterBank.CancelEdit()
Heater bank: 0
  Stage: 0
    Element: 0

Edit clicked

Before HeaterBank.BeginEdit()
Heater bank: 0
  Stage: 0
    Element: 0

After HeaterBank.BeginEdit()
Heater bank: 1
  Stage: 1
    Element: 1

After bind Stages
Heater bank: 1
  Stage: 2
    Element: 2

Cancel clicked

Before unbind Elements
Heater bank: 1
  Stage: 2
    Element: 2

Elements unbound, before unbind Stages
Heater bank: 1
  Stage: 2
    Element: 2

Stages unbound, before HeaterBank.CancelEdit()
Heater bank: 1
  Stage: 1
    Element: 2

"Edit level mismatch in UndoChanges."

Thanks in advance.
Michael

tetranz replied on Tuesday, November 17, 2009

I assume you're using WinForms. Sorry I don't have a specific suggestion but there is a parent / child / grandchild test application in the CSLA samples download. You should probably try that and make sure it works for you. Then study the binding and unbinding code. You really need to follow it exactly for it to work properly.

Michael replied on Tuesday, November 17, 2009

Hi tetranz

I'm quite familiar with the sample, and I've gone over it again to make sure I'm not doing anything silly. As the edit levels show, it is incrementing and decrementing correctly at each stage during the first edit and cancel, but it's not working the second time.

Michael replied on Tuesday, November 17, 2009

There's definitely something weird going on here. I can repeatedly edit the HeaterBank, do nothing and click OK, which calls AcceptChanges(). The Element edit level is correct each time. As soon as I click Cancel, which calls CancelEdit() it breaks.

The original problem: if I edit the HeaterBank and click Cancel the first time, it works, but fails on the second attempt.

JonnyBee replied on Wednesday, November 18, 2009

Hi Michael,

Do you have small sample project that you could post to illustrate the problem?

Are you using databound ComboBoxes on your form?

Do you control the unbind sequence and make sure that all datasources are unbound before the form controls are disposed (on FormClosed event) ?

Michael replied on Wednesday, November 18, 2009

Hi Jonny

That's an interesting suggestion. I am using a ComboBox column in the Elements grid. I'll try it out tomorrow and report back.

JonnyBee replied on Wednesday, November 18, 2009

Hi Michael,

You must make sure to Unbind the data object _before_ you you unbind the items list in your ComboBox.  If done in reverse you will end up with datatype defaultvalue in you data object property.

Michael replied on Wednesday, November 18, 2009

Hi Jonny and others

Unfortunately, unbinding all the ComboBoxes didn't make a difference. I don't understand why it only happens on the second CancelEdit(), but I have found a solution. Calling UnbindBindingSource(bindElements, saveObject) does not set bindElements.DataSource = null because its DataSource is another BindingSource. Manually setting it to null after the unbind fixes the problem. Obviously, I have to hook it back up again in BindUI(). Will I break anything else by using this approach?

Why do we implement UnbindBindingSource() this way?


public static void UnbindBindingSource(BindingSource source, bool apply)
{
    IEditableObject current = source.Current as IEditableObject;

    if (!(source.DataSource is BindingSource))
        source.DataSource = null;

    if (current != null)
        if (apply)
            current.EndEdit();
        else
            current.CancelEdit();
}


Regards
Michael


ajj3085 replied on Thursday, November 19, 2009

Have you tried changing things to use BindingSourceNode?  That made things much simplier for me.

Michael replied on Thursday, November 19, 2009

Hi Andy

I'll try BindingSourceNode, looks good, thanks for the suggestion.

Copyright (c) Marimer LLC