How to add a Field collection to a BO from related BOs?


Author
Message
Edhy Rijo
E
StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
I have a BO which I would like to have access to 2 more related BOs.  The idea is to have a property in the Parent BO to the ChildBO and in this ChildBO to another Child like this:

CustomersBO.OrdersBO.OrderItemsBO.ItemPrice

How can I do that for SF Business Object?

Edhy Rijo

Replies
Greg McGuffey
Greg McGuffey
Strategic Support Team Member (4.8K reputation)
Group: Forum Members
Posts: 2K, Visits: 6.6K
This would just be a normal property of the BO type. Note that this will work fine in code, but not for binding (at this time...there have been some posts about this very thing).



Private _parentBO As MyParentBO

Public Proprety ParentBO() As MyParentBO

Get

Return _parentBO

End Get

Set(value As MyParentBO)

_parentBO = value

End Set

End Property

Paul Chase
Paul Chase
Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)
Group: Forum Members
Posts: 414, Visits: 2.8K
Actually you can bind to your child business object's fields you just can't use the type editor to pick the binding field and business object, if you set the binding in code it works.

Me.TxtSuperVisor.BindingField = "JBO_Supervisor"

Me.TxtSuperVisor.BusinessObject = Me.BoCustomers.JobSiteBusinessObject 

Paul

Bill Cunnien
Bill Cunnien
StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)
Group: Forum Members
Posts: 785, Visits: 3.6K
Hi Edhy, Hi Greg,

I have added a custom property to my customer BO just like you outlined.  In my application, I have the CustomersBO.SalesOrdersBO being assigned to the BusinessObject property of a BusinessBindingSource.  On the CustomersBO.Navigated event, I simply swap out the related BO:

OrdersBBS.BusinessObject = customersBO.CustomerOrders;

Works like a charm with the DevEx XtraGrid control.  To setup the control, I temporarily add a SalesOrdersBO to the form.  Assign it to the BBS, then work out how I want the grid to look.  After that, I simply remove the SalesOrderBO.  I am sure something similar could be done with the next level of BOs, too.

This StrataFrame stuff is rather cool!

Bill Cunnien
Bill Cunnien
StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)
Group: Forum Members
Posts: 785, Visits: 3.6K
Wow, Paul!

While writing my response, you posted something even cooler!!  w00t w00t w00t  I shall be using that!

Smooooth
Bill

Edhy Rijo
E
StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Bill Cunnien (06/13/2008)
Hi Edhy, Hi Greg,

I have added a custom property to my customer BO just like you outlined.  In my application, I have the CustomersBO.SalesOrdersBO being assigned to the BusinessObject property of a BusinessBindingSource.  On the CustomersBO.Navigated event, I simply swap out the related BO:

OrdersBBS.BusinessObject = customersBO.CustomerOrders;

Works like a charm with the DevEx XtraGrid control.  To setup the control, I temporarily add a SalesOrdersBO to the form.  Assign it to the BBS, then work out how I want the grid to look.  After that, I simply remove the SalesOrderBO.  I am sure something similar could be done with the next level of BOs, too.

This StrataFrame stuff is rather cool!

Hi Bill,

In your case, how do you make the SalesOrdersBO in synch with the CustomerBO? so when you make a reference to a field in the CustomersBO.SalesOrdersBO.ItemPrice it will give you the price of the current selected CustomerBO record.

Edhy Rijo

Bill Cunnien
Bill Cunnien
StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)
Group: Forum Members
Posts: 785, Visits: 3.6K
I am not using a parent-child setup.  My custom property in my CustomersBO handles the plumbing:

[Browsable(false),
BusinessFieldDisplayInEditor(),
Description("Customer Orders"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public SalesOrdersBO CustomerOrders
{
   
get
   
{
       
SalesOrdersBO mSalesOrders = new SalesOrdersBO();
        mSalesOrders.FillAllOrdersByCustomer(
this.CustIndex);
       
return mSalesOrders;
    }
}

I've tweaked this whole thing several times.  I am sure that I will tweak it again.  Always finding new, more efficient ways to use StrataFrame. Smile

Bill


Paul Chase
Paul Chase
Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)Advanced StrataFrame User (806 reputation)
Group: Forum Members
Posts: 414, Visits: 2.8K
I'm sure there are more ways to do this but

1.) In the parent business objects current data table refilled event, call the child tables fill by parent method.

2.)Either set the auto filter option or filter the record yourself in the parents navigate event. just remember you have filter on it will bite you.

Or

1.) Requery the db in the parents navigated event childbo.fillbyparentpk(myparent.pk)

Edhy Rijo
E
StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Thanks a log guys,

I will start playing with the info provided right now.....Tongue

Edhy Rijo

Edhy Rijo
E
StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Well, here the working version of my code BigGrin

''' <summary>

''' Returns an instance of the InsuranceCompanyBO

''' filled with data from the current parent record.

''' </summary>

''' <value></value>

''' <returns></returns>

''' <remarks></remarks>

<Browsable(False), _

BusinessFieldDisplayInEditor(), _

Description("Insurance Company"), _

DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _

Public ReadOnly Property [InsuranceCompany]() As InsuranceCompanyBO

     Get

          Dim loLookupBO As New InsuranceCompanyBO

          If Not String.IsNullOrEmpty(Me.FK_InsuranceCompany) Then

               loLookupBO.FillByPrimaryKey(Me.FK_InsuranceCompany)

          End If

          Return loLookupBO

     End Get

End Property

And I added this property to my Function GetCustomBindablePropertyDescriptors().  It was really easy, even though during a debug session I can not really see any property of the PolicyBO.InsuranceCompany object, I would get something like this in the watch window:

  Me.PolicyBO1.InsuranceCompany.Count Evaluation of expression or statement timed out. 

Also I have to be careful when to use any property of that object since it may not have any data and would throw errors, so I do this:

If Me.PolicyBO1.InsuranceCompany.Count Then

     Dim x As String = Me.PolicyBO1.InsuranceCompany.CompanyName

     If Not String.IsNullOrEmpty(x) Then

          MessageBox.Show(x)

     End If

End If

I am sure, there should be something I could add to the property code to avoid having to keep testing for the Me.PolicyBO1.InsuranceCompany.Count Unsure

Thanks again to all of you for pointing me to the right path and if there is a way to improve this, please do not hesitate to let me know.



Edhy Rijo

Bill Cunnien
Bill Cunnien
StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)
Group: Forum Members
Posts: 785, Visits: 3.6K
This stuff sure is fun!!  w00t

Glad it is working for you...I'll keep my eyes pealed (peeled?) here in case someone does offer a better way of handling this.

Have a great weekend!
Bill

Edhy Rijo
E
StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
I am sure, there should be something I could add to the property code to avoid having to keep testing for the Me.PolicyBO1.InsuranceCompany.Count

Thinking about that, is there a way to have something like the VFP command SCATTER MEMVAR BLANK? that way I could test for the BO.count in the ParentBO and if count = 0, just create a new empty row. 

What do you think about it?

Edhy Rijo

Greg McGuffey
Greg McGuffey
Strategic Support Team Member (4.8K reputation)
Group: Forum Members
Posts: 2K, Visits: 6.6K
A couple of thoughts...



First, I don't think you need to make this a custom field property, with all the attributes. Those are needed if you want to bind the property to a control. I doubt that you will bind a BO to the property of a control. So just a normal, public property should work.



Second, you are creating and filling this BO every time you access the property. You probably want to think about caching it in a private and only creating it the first time.



Third, on you question about what to do if the BO is empty and having to test it, why not just test it in the property and add the row there? You could initialize the data in that row with values that makes sense when there is no data in the BO. Something like:



' This holds the value locally, so you don't have to keep recreating it

Private _insuranceCompany As InsuranceCompanyBO



'''

''' Returns an instance of the InsuranceCompanyBO

''' filled with data from the current parent record.

'''


'''

'''

'''

_

Public ReadOnly Property [InsuranceCompany]() As InsuranceCompanyBO

Get

If _insuranceCompany Is Nothing Then

Dim _insuranceCompany As New InsuranceCompanyBO

If Not String.IsNullOrEmpty(Me.FK_InsuranceCompany) Then

_insuranceCompany.FillByPrimaryKey(Me.FK_InsuranceCompany)

End If



'-- Check if the BO is empty...

If _insuranceCompany.Count = 0 Then

'-- Initiailize a row with appropriate values

End If

End If

Return loLookupBO

End Get



End Property




That is how I'd start in any case, plus using some of Paul's suggestions to keep parent/child BOs in synch.
Greg McGuffey
Greg McGuffey
Strategic Support Team Member (4.8K reputation)
Group: Forum Members
Posts: 2K, Visits: 6.6K
Sigh...It fubarred my codeCrazy. I didn't use html codes...In any case, I hope this is enough to keep you moving!
Edhy Rijo
E
StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Hi Greg, Bill,

Third, on you question about what to do if the BO is empty and having to test it, why not just test it in the property and add the row there? You could initialize the data in that row with values that makes sense when there is no data in the BO.

Thanks, the code is pretty understandable.  About the third option, this where a function like SCATTER MEMVAR BLANK would do the trick on initializing the empty row, unless I am just missing the simple point on using the BO.NewRow() to have a blank row with no values, so any use of its property will not throw an error.  I will test that.

Also thanks for the points about not using the descriptors, you are right and these are not needed for this kind of properties.

All the time I simply get amazed with how functionality that seems pretty difficult or hard to do are accomplish in the .NET world and of course SF with a couple of line of code.Hehe

Edhy Rijo

Greg McGuffey
Greg McGuffey
Strategic Support Team Member (4.8K reputation)
Group: Forum Members
Posts: 2K, Visits: 6.6K
Yep, I think the adding the blank row would be very easy. First you call NewRow on the BO, which adds a new row based on the table's schema:



bo.NewRow()



Then you just set the properties:



bo.InsuranceCompanyName = "None"

bo.InsuranceCompanyAddress = String.Empty

etc.



Finally, I'd call AcceptChanges on the table, so it isn't dirty (but doesn't save anything to the database):



bo.CurrentDataTable.AcceptChanges()



Easy peasy BigGrin



I agree that it is amazing how little code is often needed. Initially I spent something like a 10:1 ratio between learning and coding. Often I'd spend a couple of hours to realize it was one line of code! w00t
Edhy Rijo
E
StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Humm,

This is getting better BigGrin when changing the code as follow:

Private _insuranceCompany As InsuranceCompanyBO '--This is at the top of the class

Public ReadOnly Property [InsuranceCompany]() As InsuranceCompanyBO

     Get

          If _insuranceCompany Is Nothing Then

               Dim _insuranceCompany As New InsuranceCompanyBO

               If Not String.IsNullOrEmpty(Me.FK_InsuranceCompany) Then

                    _insuranceCompany.FillByPrimaryKey(Me.FK_InsuranceCompany)

               End If

               '-- Check if the BO is empty...

               If _insuranceCompany.Count = 0 Then

                    '-- Initiailize a row with appropriate values

                    _insuranceCompany.NewRow()

               End If

          End If

          Return _insuranceCompany

     End Get

End Property

I now get an error when trying to use this property in a code like this:

Dim x As String = Me.PolicyBO1.InsuranceCompany.CompanyName

Look at the attached image for the error: NullReferenceException was unhandled by user code.  Object reference not set to an instance of an object.

What I understand about this error is that I would need to create an instance of this object in order to use this property, while when using the original method there was not need to do that, guess because previous method was always creating an instance of the class with this code:

Dim loLookupBO As New InsuranceCompanyBO

 

Edhy Rijo

Greg McGuffey
Greg McGuffey
Strategic Support Team Member (4.8K reputation)
Group: Forum Members
Posts: 2K, Visits: 6.6K
When you call new row, I think is just adds a new row to the data table, with the values being set to whatever is the default for their type. For strings, that is Nothing (null), hence the error.



Don't forget the other part of the code, which is to set values of that new row:

_insuranceCompany.InsuranceCompanyName = String.Empty

...etc.




Do this right after you call NewRow()
Edhy Rijo
E
StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Greg,

So far, the error has nothing to do with setting values to the created new row.  When using BO.NewRow() SF will populate it with the default values which are good enough in my case.

In order to make it work I added a "New" command to initialize the Private BO variable like this:

Private _insuranceCompany As New InsuranceCompanyBO

Then I made some changes to the property code to make sure the BO is filled all the time, like this:

Public ReadOnly Property [InsuranceCompany]() As InsuranceCompanyBO

     Get

          '-- If the private BO has not been created, then create it here.

          If _insuranceCompany Is Nothing Then

               Dim _insuranceCompany As New InsuranceCompanyBO

          End If

          If Not String.IsNullOrEmpty(Me.FK_InsuranceCompany) Then

               _insuranceCompany.FillByPrimaryKey(Me.FK_InsuranceCompany)

          End If

          '-- Check if the BO is empty...

          '-- Initiailize a new row, default values could be added here if needed.

          If _insuranceCompany.Count = 0 Then

               _insuranceCompany.NewRow()

               '-- AcceptChanges on the table, so it isn't dirty (but doesn't save anything to the database)

               _insuranceCompany.CurrentDataTable.AcceptChanges()

          End If

          Return _insuranceCompany

     End Get

End Property

So far the code above is working fine. Smile

Edhy Rijo

Edhy Rijo
E
StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Greg McGuffey (06/13/2008)
This would just be a normal property of the BO type. Note that this will work fine in code, but not for binding (at this time...there have been some posts about this very thing).

Private _parentBO As MyParentBO
Public Proprety ParentBO() As MyParentBO
Get
Return _parentBO
End Get
Set(value As MyParentBO)
_parentBO = value
End Set
End Property

Hi Greg,

Thanks, but one more question, at some point I need to add code to make the ParentBO property in synch with the current record, where and how to do this?

I understand that in my Parent BO I will add a property to the ChildBO, but I want it to be in synch with the current selected parent record.  Also I don't have plans to use this for binding, just to get access to related child record for some custom functions and methods I will have in the BOs.

Edhy Rijo

GO

Merge Selected

Merge into selected topic...



Merge into merge target...



Merge into a specific topic ID...




Threaded View
Threaded View
Edhy Rijo - 17 Years Ago
Greg McGuffey - 17 Years Ago
Paul Chase - 17 Years Ago
Bill Cunnien - 17 Years Ago
Bill Cunnien - 17 Years Ago
Edhy Rijo - 17 Years Ago
                     I am not using a parent-child setup. My custom property in...
Bill Cunnien - 17 Years Ago
Paul Chase - 17 Years Ago
                         Thanks a log guys, I will start playing with the info provided right...
Edhy Rijo - 17 Years Ago
                             Well, here the working version of my code :D [quote][codesnippet]...
Edhy Rijo - 17 Years Ago
                                 This stuff sure is fun!! :w00t: Glad it is working for you...I'll...
Bill Cunnien - 17 Years Ago
                                 [quote]I am sure, there should be something I could add to the...
Edhy Rijo - 17 Years Ago
                                     A couple of thoughts...

First, I don't think you need to...
Greg McGuffey - 17 Years Ago
                                         Sigh...It fubarred my code:crazy:. I didn't use html codes...In any...
Greg McGuffey - 17 Years Ago
                                             Hi Greg, Bill, [quote]Third, on you question about what to do if the...
Edhy Rijo - 17 Years Ago
                                                 Yep, I think the adding the blank row would be very easy. First you...
Greg McGuffey - 17 Years Ago
                                                 Humm, This is getting better :D when changing the code as follow:...
Edhy Rijo - 17 Years Ago
                                                     When you call new row, I think is just adds a new row to the data...
Greg McGuffey - 17 Years Ago
                                                         Greg, So far, the error has nothing to do with setting values to the...
Edhy Rijo - 17 Years Ago
Edhy Rijo - 17 Years Ago

Similar Topics

Reading This Topic

Login

Explore
Messages
Mentions
Search