By StarkMike - 4/27/2006
I just finished tutorial 14, Configuring a Business Object relationship, and when i got to the end it said "Designing a child form that will show use of a business object relationship is beyond the scope of this tutorial". Well I've looked through the help file and the forums and can't find a parent-child tutorial.
So my question is how do i create a form with two grids on it to demonstrate how this business object relationship works.
|
By StrataFrame Team - 4/27/2006
Mike,
Do you want to have a child form that pops up and shows a child grid, or do you want to put both grids on the same form (or maybe on different tabs...)?
|
By StarkMike - 4/27/2006
If you could instruct me on samples of both that would be great! Both a child form that pops up and a parent child on the same form (two data grids).
|
By StrataFrame Team - 4/27/2006
Well, Mike,
The ChildFormDialog is used when you want to show a child form:
1) Drop one on a form
2) Set it's ChildForm property to the type of child form that it should show
3) Set the BusinessObjectTranslations property through the editor and tell it which business objects on the main form should translate into business objects on the child form.
4) Within code, call ChildFormDialog.ShowDialog() to show the child form. The business objects configured in the BusinessObjectTranslations will be translated so that the instances on the main form are the same instances that are on the child form.
When you want to use 2 grids on the same form, you simply place both grids on the form, set the DataSource on one as the parent business object and the DataSource on the other as the child business object. Within the Navigated event of the parent business object, you can repopulate the child business object so that is shows the child records of the selected business object within the parent grid. Or you can set the ChildAutoFilterOption (AutoChildFilterOption?) on the parent business object to MatchCurrentRow and the parent business object will set the filter on the child business object so that only child records of the currently selected row within the parent grid are visible within the child grid.
|
By StarkMike - 4/28/2006
I've created the business object, added a Standard SF form and dropped a DataGridView onto it. I've set the datasource on the grid to the business object. Couple of questions though... why am i gettng all these weird column names in my grid? (See attached screen shot).
Also when I run the form it only displays one record not all of them... and the SQL statement in the BO is SELECT * FROM Authors.
Thanks
|
By Trent L. Taylor - 4/28/2006
Mike,To show all rows in the BO, set the IsListSource property on the business object to True. To remove the other fields, you can edit the columns and remove them. As to why they show has to do with use using properties as strong-tped fields. I will look into and see if there is a way for use to dynaimcally remove the others, but at least there is a work around for now  Hope this helps.
|
By StarkMike - 4/28/2006
Yes Trent it did help. I'm getting closer. 
Ben had posted this earlier and I'm not sure what he meant by this:
4) Within code, call ChildFormDialog.ShowDialog() to show the child form. The business objects configured in the BusinessObjectTranslations will be translated so that the instances on the main form are the same instances that are on the child form.
Where within code am I supposed to put the ShowDialog line? What if i wanted the child form to pop-up on double click of a row?
|
By StrataFrame Team - 4/28/2006
If you wanted the form to show in the double-click of a row, then you would add a handler to the grid's double-click event and place the code in there.
Private Sub DataGridView1_DoubleClick(ByVal sender As Object, ByVal e As EventArgs)
'-- Call the child form
Me.MyChildFormDialog.ShowDialog()
End Sub
|
By StarkMike - 4/28/2006
Ok, on one form i have two grids and i have everything setup correctly, i think, i have both grids filling with data... but when i move between rows on the parent grid the child grid isnt synching... Any ideas?
|
By StrataFrame Team - 4/28/2006
What data are you pulling in?
Are you pulling a set of parent records and then also pulling in all of the child records for those parent records?
|
By StarkMike - 4/28/2006
My sample is based on the pubs table, would it be easier for you to debug if I attached the project?
|
By StrataFrame Team - 4/28/2006
Nah, don't worry about attaching the project. This is what I did:
1) Put the parent business object in DataGridView1 and the child in DataGridView2.
2) Handled the DataGridView1.Click event with this code:
Private Sub DataGridView1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataGridView1.Click
If Me.DataGridView1.SelectedRows.Count = 1 Then
Me.BusinessObject11.Navigate(MicroFour.StrataFrame.Business.BusinessNavigationDirection.Absolute, Me.DataGridView1.SelectedRows(0).Index)
ElseIf Me.DataGridView1.SelectedCells.Count = 1 Then
Me.BusinessObject11.Navigate(MicroFour.StrataFrame.Business.BusinessNavigationDirection.Absolute, Me.DataGridView1.SelectedCells(0).RowIndex)
End If
End Sub
3) Set the ChildAutoFilterOption on the parent business object to MatchCurrentRow.
4) Made sure that the parent business object was set as the ParentBusinessObject on the child business object.
With those steps, when you click on the parent grid, it will filter the child records so that only the records within the child business object that match the currently selected parent will be visible.
Now, if you want to requery the database for child records each time you click on a parent record, you'll need to add an event handler for the Navigated event on the parent business object and repopulate the child business object with the appropriate records.
|
By StarkMike - 5/1/2006
Ok, I feel a little confused and am not sure why i haven't got this to work. So I am going to reiterate what I have done to this point and we'll go from there.
I've created two business objects, a parent and a child. Both of these business objects are being filled through their ParentFormLoading events.
I've configured the ParentRelationship property on the child business object's class.
I've set the ParentBusinessObject property on the child business object.
I've set the ChildAutoFilter property on the parent business object to MatchCurrentRow.
Both of the business objects are filling properly with data, but I dont see any records in the child grid.
Have I forgot something?
|
By StrataFrame Team - 5/1/2006
Make sure that both of your business objects' IsListSource properties are set to True.
After that, Mike, you haven't forgotten anything... what you can do is this:
Set a breakpoint in a button on the form so that we can check some of the values on the business objects at runtime in the Watch window.
Check the ChildBO.CurrentDataTable.Rows.Count property on the child business object and make sure it's greater than 0.
Check the ChildBO.Count property on the child business object and see if it's greater than 0. This value will tell you the number of visible records within the business object while the above value will tell you the number of records, visible or not.
Check the ChildBO.Filter property... it should be set to a value like this: "my_fk='parentpkvalue'" which hides all records within the child business object that don't match the current row within the parent business object. This value should follow the relationship you've defined on the business objects. If it doesn't then we have a problem
|
By StarkMike - 5/1/2006
The ChildBO.CurrentDataTable.Rows.Count was equal to 18.
The ChildBO.Count was equal to 0.
The ChildBO.Filter was equal to 1=0.
|
By StrataFrame Team - 5/1/2006
OK, well that explains that... 1=0 will hide all child records.
Whenever there are no records visible within the parent business object, the filter is set to that value so that it will hide the records within the child business object as well. This is kind of a bootstrap issue, because the child records are filtered whenever the ParentBusinessObject property is set on the child business object, and that happens during the form's InitializeComponent() method, and both business objects are empty.
Add this line of code in the parent business object's ParentFormLoading event handler, right after you fill it:
ParentBO.FilterChildRecords()
This will go through the filter logic again, and filter the records properly. After that, the records will be filtered automatically when the record within the parent business object is navigated.
|
By StarkMike - 5/1/2006
Ok I added the code like you said and it did filter the chlid records for the first record in the parent business object. However it did not refresh the child filter upon navigation of the parent records.
The ChildBO.filter property returned this value: "pub_id=0736", the first row in the ParentBO.
|
By StrataFrame Team - 5/1/2006
Ah, yes, I assume you're using the .NET DataGridView, correct?
The business objects do not automatically attach to the events on the grids, and the grids do not notify the business objects to navigate, since the grid views the business object as a big, flat list. So, within the RowClicked and/or CellClicked events of the grid, you will need to call:
ParentBO.Navigate(BusinessNavigationDirection.Absolute, e.RowIndex)
This will tell the business object to navigate to the desired record, thereby synching with the child business object.
|
By StarkMike - 5/1/2006
Thanks, works now. A couple related questions. When I move to a record in the parent grid that doesnt have related child records it doesnt clear the grid, it just leaves the records from the previous record.
Plus when I tried to add a child record I got an error. I have attached a screen shot of that error. Keep in mind that I am using the pubs database and my parent is Publishers and my child is Titles. I think it has something to do with the primary key in Titles being Alphanumeric. Not sure how to resolve the problem though.
Thanks
|
By StarkMike - 5/1/2006
And another question.... If I wanted to put an Orders grid at the bottom of the CustomerMaintenance form found in the Tutorials what event from the Maintenance form would I use to put my ParentBO.Navigate code in? So that the orders would refresh each time i went to a different customer.
Thanks
|
By StrataFrame Team - 5/1/2006
You wouldn't need to put any code there because the navigation buttons on the MaintenanceFormToolstrip call the Navigate() methods on the business object(s), so the Navigated event is already getting raised (which re-filters the children automatically). The reason you have handle events on the parent grid in your scenario is because of the flat list problem... the grid doesn't need to navigate records, so you have to Navigate the business object manually. With the maintenance form toolstrip, and the way the CustomerMaintenance form works, you have to call Navigate to move to another record.
|
By StarkMike - 5/2/2006
Thanks Ben, I'll look into that. I posted two things in a row. Please look at post 1033.
http://forum.strataframe.net/FindPost1033.aspx
|
By StrataFrame Team - 5/2/2006
The error you're getting when trying to insert the child record is because the Titles business object is configured with PrimaryKeyIsAutoIncremented = True, and the primary key can only be auto-incremented for numeric data types. Since the primary key is not an auto-incremented value, you'll need to set the PrimaryKeyIsAutoIncremented property to False and assign a valid PK value for the new child record before saving. Basically, the server cannot assign the PK value, you'll have to assign it on the client side.
|
By StrataFrame Team - 5/2/2006
As for the child grid not being cleared when you select a record that has no child records, put a handler on the TitlesBO.FilterChanged event and within it, put a message box, or a Debug.WriteLine() call within it and print the TitlesBO.Filter value. Basically, I want to make sure the filter is being set whenever you select a record that doesn't have any child records.
|
By StarkMike - 5/2/2006
As for the child grid not being cleared when you select a record that has no child records, put a handler on the TitlesBO.FilterChanged event and within it, put a message box, or a Debug.WriteLine() call within it and print the TitlesBO.Filter value. Basically, I want to make sure the filter is being set whenever you select a record that doesn't have any child records.
I'll try that.
Another question. I have the Customer Maintenance form and I have a parent child relationship setup with the Orders table. There is a grid on the maintenance form that displays the customers orders. I have everything setup correctly (i think) and when i run the program there is no errors but the navigation buttons are disabled. The first customer doesnt have any related orders. I dont know if that has anything to do with it.
|
By StrataFrame Team - 5/2/2006
Make sure that the IncludeInFormNavigateType property on the CustomerMaintenance form is set to PrimaryBusinessObject and make sure that CustomersBO1 is set as the PrimaryBusinessObject on the form. For some reason, it looks like your form thinks it's supposed to be navigating Orders instead of Customers.
|
By StarkMike - 5/2/2006
I've checked both those things and they were set properly. I turned the ChildAutofilter property off and ran the program and it worked fine. I was able to navigate the customer form and the all the orders filled the grid. When I set ChildAutoFilter to MatchCurrentRow I got the attaced error.
|
By StrataFrame Team - 5/2/2006
I believe that there is already code within the Navigate method on that form that's requerying the database for the orders. You can either requery like that form is doing, or you can fill the parent and child with all of the necessary records and then let the child filtering do its thing. But, if you try to use both methods, you're going to run into problems.
|
By StarkMike - 5/2/2006
Sorry, I dont understand. I have the SQL statements in the business objects that will be used to fill them. Then in the form I call those Fill methods in each BO's ParentFormLoading Event. You're saying not to fill the BO's on load?
This thread seems like its taking on a life of its own.
|
By StrataFrame Team - 5/2/2006
Yes, this thread seems to be more of a chat window 
Basically, there are two methods you can use to accomplish what you're trying to do:
1) Fill both business objects in their respective ParentFormLoading events. Use the relationship and the ChildAutoFilterOption to let the parent business object filter the children. This is the option you want to use to reduce network traffic and requeries against the database. However, if you have several thousand child records, this wouldn't be the option you would want to use.
2) Fill just the parent business object in its ParentFormLoading event. Then, in its Navigated event, fill the child business object will only the records that belong to the current parent, say, using the FillByParentPrimaryKey() method on the child business object and passing it the current pk of the parent. This is the method you want to use if you don't care about network traffic or you have several thousand child records, since you don't have to bring them across all at the same time.
Method #2 is the method that the tutorial is using, while Method #1 is the way you're sample is handling the issue. Both are correct, and both have their uses, but you can't mix them because it could cause problems with the order that the filter is being set and the child is being filled.
|