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.
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.
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?
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.
Wrong thread...sorry
Ok. In child WinPart, should we use child.IsDirty or root.IsDirty?
Sorry, i found the problem.
Child(or children) should be a property of Parent and when you create a Child mark it as a Child.
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?
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.
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.
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.
No, i don't use the BindingSourceExtensions. I call BeginEdit in my own code in RebindUI. I this case, do you have suggestion?
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.
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.
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;
}
There seems be another helper class- ActionExtender. Waht's that for? What situation should the two be used?
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.
Do you have any thought on my code above?
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.
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();
}
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().
Yes, that could be the source of your problem.
Stiil no luck after dealing with them.
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