Child edit level increases when screen disposed

Child edit level increases when screen disposed

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


Michael posted on Wednesday, July 15, 2009

I have a root BB with a child BLB bound to two bindingsources. Performing an edit on one of the child objects and clicking OK correctly does a save and close. The newly saved root object gets updated back to the main form's relevant tree node, and the edit levels are 0 for the root and all children.

However, when I do the same edit, and click Apply, then Close, everything works fine with 0 edit levels until the main form calls Dispose() on the screen, at which point the child that was edited has its edit level raised to 1. So, opening the edit screen for the root object again throws an UndoException.

I've tried a number of different things, and I've looked over the Project Tracker and RootChildGrandchild samples again. But, I feel like I'm taking crazy pills!

EDIT: If I make the children's bindingsource independent by making its DataSource = typeof(Children) instead of DataSource = Root and DataMember = Children, and in BindUI() call childrenBindingSource.DataSource = root.Children, the problem disappears. It's not really the solution I was hoping for, so I'd still like to hear any thoughts.

Regards
Michael

RockfordLhotka replied on Thursday, July 16, 2009

CSLA objects don't support being bound to more than one bindingSource at this time.

This issue is known, and is in the wish list as something to address. It means implementing something like reference counting in the IEditableObject implementation, which means altering support for data binding (obviously I guess). Since testing the ramifications of any data binding changes is really intense, this change is one I may make - but only when I have several days free to test/debug/troubleshoot.

Michael replied on Thursday, July 16, 2009

Hi Rocky

Thanks for the reply. I didn't really explain it properly. What I meant was I have a root BB bound to a rootBindingSource and a children BLB bound to a childrenBindingSource. The childrenBindingSource's DataSource is the rootBindingSource, with DataMember set to Children. It's a stock-standard scenario, which is why I'm so perplexed with the weird Dispose() behaviour.

Regards
Michael

rsbaker0 replied on Thursday, July 16, 2009

This is not a fix, but perhaps you could workaround this by unbinding your object from the bindingsource when the screen is closed (OnHandleDestroyed override if I remember correctly).

Michael replied on Wednesday, August 05, 2009

Unfortunately, OnHandleDestroyed() doesn't fire until after Dispose().

I've just recently had to revisit this, because Dispose() was throwing:
ArgumentException was unhandled
Cannot bind to the property or column (PropertyName) on the DataSource.
Parameter name: dataMember

This exception can be thrown if you forget to hook up the DataSource on an ErrorProvider, but this was a different problem.

This was happening on the
childrenBindingSource when set up as an independent binding source as described in the first post. The only way I could work out how to fix it was to add the following to RebindUI():

if (!rebind)
    childrenBindingSource.DataSource = typeof(Children)
;

EDIT: This problem is discussed here: http://forums.lhotka.net/forums/thread/709.aspx
As Andy says, "
It only seems to affect the ComboBoxes bound to the NameValueLists AND the Text property is databound."

Looks like a bug in .NET.

Regards
Michael

JonnyBee replied on Thursday, August 06, 2009

Hi,

This is because you are probably not doing a controlled UnBind of your bindingsources.

I always tell my developers to make a controlled UnBind inWindows Forms. What happens is probably you have some combobox'es and the datasource for the combobox'es are disposed before the "root" bindingsource and the data values from comboboxes are destroyed when its items are removed (bindingsource unbound) but still the SelectedValue or SelectedText databinding is active.

So I always have 2 methods in my Forms:
private void BindUI() {
    // 1. connect all bindingsources for combobox or other listitems
 
    // 2. Connect the "data" bindingsources - root first

}

private void UnbindUI()  {
   // 1. unbind all data binding sources - reverse order for BindUI
   //      start at lowest level and "root" is the last

   // 2. Unbind bindingsources for combox or other listsitems
}

The UI must be UnBound before it is Disposed - in f.ex the Closing event on your Form.

/jonnybee

JonnyBee replied on Thursday, August 06, 2009

Hi,

I use this class all the time in my Forms apps for Rebind/UnbindBindingSource - try it out.

See attched zipfile for code.

/jonnybee

Copyright (c) Marimer LLC