Working with child BO - Windows Form

Working with child BO - Windows Form

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


fredg posted on Friday, February 24, 2012

Hi, we're working on windows form project. There is parent-child relationship for our BOs. Parent WinPart is dealing with only Parent BO without problem.

Our child WinPart ONLY deals with child BO, too. My question is:

 Do we need to pass parent BO instance to child WinPart and get child BO from parent BO, or pass both parent/child BOs, or just pass child BO?

  More specific, do we need to set databinding to parent BO/child BO or just set child databinding?

  In RebindUI() method, parent.Save()/parent.ApplyEdit()/..  or child.Save()/child.ApplyEdit()/..  should be called?

Thanks in advance.

JonnyBee replied on Friday, February 24, 2012

No, you do not need to send the parent object to the child win part but you must follow the guidelines for bind/unbind in Windows Forms.

Read more here: http://jonnybekkum.wordpress.com/2009/10/20/forms-databinding-the-magic-sequence-of-binduiunbindui/

And also important to understand DataBindingFAQ available at WindowsClient.Net.

So:

1. You can set child databinding only in child winpart

2. Always unbind in correct sequence from all BindingSources.

3. Before you can call save on the "root" object

4. the rebind object to BindingSources.

 

 

fredg replied on Friday, February 24, 2012

Thanks for your answer. So in this case, we only need to call child.Save()/child.ApplyEdit()/... in RebindUI() method? And there is nothing do to with root object in the child WinPart?

JonnyBee replied on Friday, February 24, 2012

You cannot call save on a child object !!!!!

You must always have a root object and can only call Save on the "root" object - not on any child object!!

If you call Save on a child object the DataPortal will throw an Exception.

Pavel replied on Friday, February 24, 2012

Wrong thread...sorry

fredg replied on Friday, February 24, 2012

Ok. In child WinPart, should we use child.IsDirty or root.IsDirty?

Sorry, i found the problem.

Pavel replied on Friday, February 24, 2012

Child(or children) should be a property of Parent and when you create a Child mark it as a Child.

 

fredg replied on Tuesday, February 28, 2012

Another question: If in child winpart, we only pass child BO and databind to child BO, when calling UnbindingSource(childBindingSource, isRoot), what value should we pass for isRoot, true or false?

JonnyBee replied on Tuesday, February 28, 2012

You should pass in true whenever an object is directly bound to the BindingSource

ie: use false when BindingSource has another BindingSource as DataSource and a property on that source as DataMember.
     use true BindingSource has a <bo> as DataSource.

 

fredg replied on Tuesday, February 28, 2012

Then should we call root.ApplyEdit()/root.BeginEdit() or child.ApplyEdit()/child.BeginEdit() ?

My problem is: when calling root.BeginEdit() in RebindUI(), an error of Edit Level mismatch in CopyState happens.

JonnyBee replied on Tuesday, February 28, 2012

Do you use the BindingSourceExtensions from CslaContrib.Windows?

Do you call BeginEdit in your own code in RebindUI?

If so I would only call BeginEdit() on the Root object - and that must before any BindingSource is connected to any <bo> in the object structure.

fredg replied on Tuesday, February 28, 2012

No, i don't use the BindingSourceExtensions. I call BeginEdit in my own code in RebindUI. I this case, do you have suggestion?

fredg replied on Wednesday, February 29, 2012

Hi, for a windows form project, I'm working on a grand child winpart. The winpart only diaplays a datagridview which is bound to grandchild collection.

When there is only 1 grandchild, saving is ok. But when there are 2 grand children, saving throws "Edit level mismatch on CopyState()" in root.BeginEdit() method.

root.BeginEdit()  is called from RebindUI() and i'm not using BindingSourceExtensions.

Any thought on this? Thanks in advance.

 

JonnyBee replied on Wednesday, February 29, 2012

Can you post the code in Unbind / Rebind?

I do recommend to use the BindingHelperExtensions. Some hard learned lessons in there regarding the problems that you have here.

fredg replied on Wednesday, February 29, 2012

My code is following. (((ApplicationForm)this.ParentForm).CurrentDeal is referencing to root.

Deal is root. Property is child. Rentroll is grand child in my case. I'm currently working on grand child winpart.

------------------------------------------------------------------------------------

        private void RebindUI(bool saveObject, bool rebind)
        {
            this.propertyBindingSource.RaiseListChangedEvents = false;
            this.propertyRentRollsBindingSource.RaiseListChangedEvents = false;

            try
            {
                UnbindBindingSource(this.propertyRentRollsBindingSource, saveObject, false);
                UnbindBindingSource(this.propertyBindingSource, saveObject, true);

                this.propertyRentRollsBindingSource.DataSource = this.propertyBindingSource;

                // save or cancel changes
                if (saveObject)
                {
                    ((ApplicationForm)this.ParentForm).CurrentDeal.ApplyEdit();

                    try
                    {
                        ((ApplicationForm)this.ParentForm).CurrentDeal = ((ApplicationForm)this.ParentForm).CurrentDeal.Save() as IDeal;

                        _property = ((ApplicationForm)this.ParentForm).CurrentDeal.DealProperties[_property.RowGuid];

                    }
                    catch (Csla.DataPortalException ex)
                    {
                        _dictionary["StackTrace"] = ex.StackTrace;
                    }
                    catch (Exception ex)
                    {
                        _dictionary["StackTrace"] = ex.StackTrace;
                    }
                }
                else
                {
                    ((ApplicationForm)this.ParentForm).CurrentDeal.CancelEdit();
                }
            }
            finally
            {
                // rebind UI if requested
                if (rebind)
                {
                    ((ApplicationForm)this.ParentForm).CurrentDeal.BeginEdit();

                    BindUI();
                }

                // restore events               
                this.propertyBindingSource.RaiseListChangedEvents = true;
                this.propertyRentRollsBindingSource.RaiseListChangedEvents = true;

                if (rebind)
                {
                    // refresh the UI if rebinding                   
                    this.propertyBindingSource.ResetBindings(false);
                    this.propertyRentRollsBindingSource.ResetBindings(false);
                }
            }
        }

        private void BindUI()
        {           
            this.propertyBindingSource.DataSource = _property;         
        }

fredg replied on Wednesday, February 29, 2012

There seems be another helper class- ActionExtender. Waht's that for? What situation should the two be used?

JonnyBee replied on Wednesday, February 29, 2012

Look at the ActionExtender sample in the samples download.

Beware tho' that there is a few bugs reported that haven't been prioritized for CSLA 4.

fredg replied on Wednesday, February 29, 2012

Do you have any thought on my code above?

JonnyBee replied on Wednesday, February 29, 2012

Do you call Save in your root object from the child win part?

I'd rather have a SaveDeal procedure in the "Parent" form and make sure the ALL winparts/bindingsources are Unbound from the entire object structure before you call Save an the Rebind afterwards.

And you should NEVER call BeginEdit/CancelEdit/ApplyEdit manually for as long as DataBinding is active.
DataBinding will call these methods very often and assume they have total control of these methods.

My preference is to only call BeginEdit on the "root" object unless some very special need says otherwise before databinding. 

Plus - you did not include the code for UnbindBindingSource method.

 

 

 

fredg replied on Wednesday, February 29, 2012

All my call to Save()/BeginEdit/CancelEdit/ApplyEdit  are on root object.

The code for UnbindBindingSource:

        protected void UnbindBindingSource(BindingSource source, bool apply, bool isRoot)
        {
            System.ComponentModel.IEditableObject current =
              source.Current as System.ComponentModel.IEditableObject;
            if (isRoot)
                source.DataSource = null;
            if (current != null)
                if (apply)
                    current.EndEdit();
                else
                    current.CancelEdit();
        }

fredg replied on Thursday, March 01, 2012

Forget to metion: i also used multiple combox to bind to other bindingSources in the datagridview. Do I need to do sth for those bindingsources in my RebindUI()? Is it possible those bindingsouces cause the "Edit Level mismatch in CopyState" error? But in ProjectTracker project, this kind of bindingsources for combox(e.g.RoleListBindingsource) is not dealt inside RebindUI().

JonnyBee replied on Thursday, March 01, 2012

Yes, that could be the source of your problem.

fredg replied on Thursday, March 01, 2012

Stiil no luck after dealing with them.

fredg replied on Friday, March 02, 2012

If we're not caring about the un-do provided by CSLA.net(e.g. when canclling editing, just retrieving BO from database and rebind UI.), can we disable the edit level of the BO?How can we do that?

Copyright (c) Marimer LLC