Edit level problem with root/child/grandchildEdit 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