Parent BO calculated property value using Child BO's

Parent BO calculated property value using Child BO's

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


cultofluna posted on Thursday, May 31, 2007

Hello,

I have a parent BO that has a list of child BO's. For each child BO the user can manually enter a weight. The parent BO has a property that calculates the sum of the weights for the child BO's.
I use Winforms to present the BO's and the parent BO is known by it's child BO's.

When I change the weight of a child BO the parent BO should be informed that a change has been made and fire a PropertyHasChanged for the user to see the weight of the parent changed.

However what is the correct way to implement? How can I let the parent BO know a child BO has changed? Using PropertyChanged event?

Any thoughts?

Regards,

skagen00 replied on Thursday, May 31, 2007

In order for WinForms databinding to refresh the parent "sum" I suppose you could attach a handler in the parent object to the listchanged event of the list of children - capture deletes and itemchanged for the weight property and then do as you say - fire the property changed for the parent's property (which I assume sums up the child weights).

The insert case probably doesn't matter since I imagine their default value is 0 or null.

Chris

 

 

 

 

Q Johnson replied on Thursday, May 31, 2007

I don't have real knowledge of your use case here, of course. 

But it usually seems to me that functionality that needs access to all the members of a List is properly the responsibility of that List (rather than the EditableRoot object of which that List object is a property).  If the parent object needs the value of the weight of the entire collection, it can retrieve as simply as it gets the .Count propert of the List, right?

If you see it the same way, you just need to wire the handler suggested in Chris' post to the List object.  The handler would presumably update the value of the List's new property (.Weight).  When Parent needs it, they just use <ChildListName>.Weight.

 

skagen00 replied on Thursday, May 31, 2007

Yeah, the parent would be respondent to the list saying "I've changed!".

The reason why the parent needs to know the list has changed isn't so much to do with object design per say in this case (the list could definitely have the sum too) but rather with Winforms databinding I believe - the parent's sum display won't automatically refresh unless you tell it to - so the parent needs to be able to subscribe to something that'll tell it when the sum changes so it can trigger this refresh.

(I work entirely in the Web but this is how I remember the issues in Win)

cultofluna replied on Thursday, May 31, 2007

Hey, thanks for the answers so far!

That's exactly what I did. I've created a .Sum like property that simply sums all the weights of the child BO's. This property is exposed through the parent BO.

The problem is as Chris says, the Winform won't refresh. Isn't the list changed event a pretty expensive event? As it seems to respond to every change in the child BO?

Regards,

ajj3085 replied on Friday, June 01, 2007

You're on the right track.  As others have pointed out, there's no meaningful way to databind to a property on a list object.. so your sumation which DOES belong on that class should be there, but internal.

What you need to do in the object which contains the list object is have the parent listen to the ListChanged event.  The ListChanged event is no more expensive than any other event.  Yes it will respond to every change in the child, but you're limited by how fast a user may change each property of a child.  So the parent's ListTotal property changed will be fired more often, but in reality its only two bindings that would be affected.

Here's how I typically handle this:
public MyBLB Children {
   get { return children; }
   private set {
       if ( children != value ) {
             if ( children != null ) {
                   children.ListChanged -= Children_ListChanged;
             }
             children = value;
             if ( children != null ) {
                   children.ListChanged += Children_ListChanged;
             }
       }
}

private void Children_ListChanged( object sender, ListChangedEventArgs e ) {
    PropertyHasChange( "ListTotal" );
}

I always use the list Property when initalizing, so that the event handlers get unhooked / hooked properly.

protected override void DataPortal_Create() {
    // Other code
    Children = MyBLB.New();
}

ward0093 replied on Wednesday, July 25, 2007

i need to bring this topic back up because I have a very similiar issue...  I have a parent BO with child collection of childBOs... I have a property in my Parent BO cause LineItemsTotal that simply references the child collection property called LineItemsTotal which interns does the sumation of all the childrens LineItemTotal.

Now I can trap the ListChanged Event of the child collection object in my ParentBO... but there is no way to tell which property had changed?  I do not want to fire off a PropertyHasChanged("LineItemsTotal") in my parent BO for every single item changed event in the child collection... the event would be fire thousands of times.

how do you find out which child bo property did the listchange event firing?

ward0093

skagen00 replied on Wednesday, July 25, 2007

ListChanged will tell you the property that changed, I'm pretty sure.

You'd also want to accomodate it for when an item is removed (and added if the default amount for that line is somehow non-zero).

edit: System.ComponentModel.ListChangedEventArgs e

ward0093 replied on Thursday, July 26, 2007

i thought e.PropertyDescriptor was set to nothing but that is not true with the ItemChanged ListChanged Event arg type so that should work.

thanks,
ward0093

ward0093 replied on Thursday, July 26, 2007

why is e.PropertyDescriptor is set to null when ListChangedType = ItemChanged?  I can not evalulate it if the PropertyDescriptor is not set!

anyone have an answer to this?

ward0093

Copyright (c) Marimer LLC