Hi,
I have Pay object with a collection of line items which in turn has line items contained within. Now my question is this (in VB.NET with the 2.03 CSLA) how do I get the totals recalculated when a line item's property changes.
ie. If the hours change etc.
and please feel free to be precise because I have looked a few examples and the theory makes sense but I don't know how to implement it
Thanks
If all of your objects are CSLA-type BO's, then the child objects (line items) should already expose a PropertyChanged type event that can be handled by the parent collection - and should already be in order to implement IsDirty. Simply add the call to recalculate your total to the existing event handler.
Or, to save yourself from having to iterate over all of the child items each time in order to recalculate, create a new event, something like AmountChanged with the previous amount and new amount as eventarg parameters. Then add a handler to each child object as it is added to the collection. In the event handler, simply calculate the adjustment you need to make to the total by finding the difference in the child item's amount: _total = _total - (e.OldAmount - e.NewAmount).
You can clean it up and make the symantics a bit more appealing but those are two of the easiest ways to go and maintain a more decoupled relationship between the child objects and their parents.
Going with the previous suggestion where you call a method in the parent object from the child directly couples the child objects to their parent meaning that you can only use the LineItem (child object) within your Pay object. If you wanted to reuse the object elsewhere, you'd have problems.
Hope that helps.
Conceptuually yes, practically no.
I don't know what the code would be, could you please give me an example ie. Which event handler ?
Thanks
Wal972:Still needing help desperately thanks
Thanks for the ideas, howver i repeat i don't know what code to write. I have a lineitem collection which has the required calculating code, but i don't know how to activate it when a particular line item changes. CAN SOMEONE PLEASE PROVIDE A SAMPLE CODE OF WHAT IS REQUIRED
UEGENT
THANKS
Thanks Dean
Ok I can implement step 1 and 2 but three is confusing me.
I'm using an interface for my line items in the collection its affecting the code help
Thanks
Ellie
Sorry for being so ignorant, but against what do I implement in each line item class
secondly if I need just the quick version for another problem, how do I trap the Propertyhaschanged event in the Collection
Thanks Heaps Dean
Ellie
The delegate types are different ?
I'm after the changes to an existing line as well new ones will the approach capture that as well
What is the quick way too, because I don't know that either
Much appreciated
But it doesn't work when there's the interface inbetween, can you please suggest something and also how I get the root object to listen to the collection listening to the propertychanged
Thanks Dean
Ellie
True but how and from where, this is new to me, so I need code examples. Also the inteface I have on the children of the collection is acting as inteferance. I can it work some of the time, like add and delete but not when a change has occured
Thanks
OK with the collection to child problem I can't get a lock on the PropertyChanged event because of the interface i am using to define the collection items. The interface doesn't have the propertychanged event and when I try to get around this it doesn't work. How do I access a child's propertychanged via an interface.
If I add the handler in the list its looking for the same signature as it. I can match that in the interface, but I can't link the interface back to the child propertychanged which is a sub not an event
Help
Also do I need to add a itemchanged as well as add and deleted. Because it does activate on the change only the add and delete.
Firstly the interface code resolved one problem but
I have added the following code yet the Calculating Code is not being called WHY ? and I need to move this to the Pay parent as well because it need properties from it. Specific code required for the parent object. HELP :) Thanks
Protected Overrides Sub OnListChanged(ByVal e As System.ComponentModel.ListChangedEventArgs)
If e.ListChangedType = ComponentModel.ListChangedType.ItemAdded Then
AddHandler Item(e.NewIndex).PropertyChanged, AddressOf OnPayChanged ElseIf e.ListChangedType = ComponentModel.ListChangedType.ItemChanged Then AddHandler Item(e.NewIndex).PropertyChanged, AddressOf OnPayChanged ElseIf e.ListChangedType = ComponentModel.ListChangedType.ItemDeleted ThenOnPayChanged(
Me, New System.ComponentModel.PropertyChangedEventArgs("PayDetails-ListChanged")) End If MyBase.OnListChanged(e) End Sub Protected Sub OnPayChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs)Calculating code
End Sub
Not sure if this is correct please advise
THANKS HEAPS EVERYONE
Its working
The way I solved this in the past is as follows.
Req object has readonly property Total (sum of child objects in
child list amount property). In the getter of it I would run through collection
and compute the sum. I would also have friend (internal) method RefreshTotal
that would only raise PropertyChange event for Total property.
I would carry parent property in child list and from each child’s
setter of the amount call this.Parent.Parent.RefreshTotal(). This way you
do not need to rely on events and you have explicit call to refresh the
total. Also, if total is not bound to the UI, you will also avoid the
overhead of actually computing it.
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: demwa
[mailto:cslanet@lhotka.net]
Sent: Wednesday, October 01, 2008 12:15 PM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] Totals and collections
I have a similar problem,How did you solve yours.I have a
parent BO called cheque Requisition which contains the child collection object
called chequerequisitionlineitems which in turn contains
chequerequisitionlineitem BO.The parent BO has the TotalAmount property which
totals the sum of the Amount property of the child BO's.Now when I change the
Amount property of the Child BO the Parent BO TotalAmount is not being updated
to reflect the changes.Anyone who can help?
Sorry for being so ignorant,plse show me the sample code for refreshTotal.
Many thanks
RefreshTotal is very simple – one line of code
OnPropertyChanged("Total")
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: demwa
[mailto:cslanet@lhotka.net]
Sent: Thursday, October 02, 2008 8:07 AM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] RE: Totals and collections
Sorry for being so ignorant,plse show me the sample code for refreshTotal.
Many thanks
Thanks for the help,but I seem to be missing something
Here is the code snipnet in the Cheque Requisition object
Public
ReadOnly Property Amount() As String Get Return Format(mChequeRequisitionLineItems.Amount, "#,##0.00") End Get End Property Friend Sub RefreshTotal()OnPropertyChanged(
"Amount") End Subin the Collection I have the following code
Friend
ReadOnly Property Amount() As Decimal GetmAmount = 0
For Each child As ChequeRequisitionLineItem In MemAmount += child.Amount
Next Return mAmount End Get End PropertyIn the child object I have the following code
Public
Property Amount() As Decimal GetCanReadProperty(
True) Return mAmount End Get Set(ByVal value As Decimal)CanWriteProperty(
True) If mAmount <> value ThenmAmount = value
PropertyHasChanged(
"Amount")End If End Set End Property
My problem is I don't to access the me.Parent.Parent.RefreshTotal in the child object.Where I have I gone wrong?
You should have access Parent (child list) in child
object. In child list you will need to add read only property for parent because
Parent property in BB and BLB is protected thus not accessible outside of the
object.
So your list will have
Friend ReadonlYproperty MyParent as Root
Return Ctype(My.Parent, Root)
Then in child’s Set Amount you will have
Ctype(Me.Parent, ChildList).MyParent.RefreshTotal()
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: demwa
[mailto:cslanet@lhotka.net]
Sent: Sunday, October 05, 2008 5:28 AM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] RE: Totals and collections
Thanks for the help,but I seem to be missing something
Here is the code snipnet in the Cheque Requisition object
Public ReadOnly Property Amount() As String
Get
Return Format(mChequeRequisitionLineItems.Amount, "#,##0.00")
End Get
End Property
Friend Sub RefreshTotal()
OnPropertyChanged("Amount")
End Sub
in the Collection I have the following code
Friend ReadOnly Property Amount() As Decimal
Get
mAmount = 0
For Each child As
ChequeRequisitionLineItem In Me
mAmount += child.Amount
Next
Return mAmount
End Get
End Property
In the child object I have the following code
Public Property Amount() As Decimal
Get
CanReadProperty(True)
Return mAmount
End Get
Set(ByVal value As
Decimal)
CanWriteProperty(True)
If mAmount <> value Then
mAmount = value
PropertyHasChanged("Amount")
End If
End Set
End Property
My problem is I don't to access the me.Parent.Parent.RefreshTotal in the
child object.Where I have I gone wrong?
Thanks for being patient with me.I still seem to have the problem when I write the code you proposed in the BLB
Public readonly property MyParent()as ChequeRequisition
get
return cytpe(my.Parent,ChequeRequisition)
End get
End property
But I am getting a syntax error because the my object does not have the parent propperty/method I have also tried the me.Parent it also does not work.Where am I going wrong.
Many thanks
Sergey,
I still need your help
Could you post your classes (or at least parts that are pertinent
to the solution) if sample below is not clear? I am not a big fan though
of custom events in CSLA. I would personally prefer direct (explicit)
interaction between objects in a graph rather than events based (implicit)
interaction. It does introduce tight coupling between objects in a graph,
but technically should not re-use objects in multiple graphs bases on single responsibility
principal. I will let you make a decision which route you would like to
go, because I am in a minority I think with my approach on this forum.
Here is how I implement my approach in 2.0 (because lists do not
have parent property in 2.0, like in 3.6/3.5)
Public Class Pay
Friend Sub UpdateTotal
OnPropertyChanged(“Total”)
When new and Fetch
_payItemsList.Parent = Me
Protected Overrides OnDesiralized
MyBase. OnDesiralized
_payItemsList.Parent = Me
Public class PayItem
Pretty much the same code as pay to maintain a parent for
PayLineItemsList
Friend Sub UpdateTotal
OnPropertyChanged(“Total”)
Ctype(Me.Parent, PayItemList).Parent.UpdateTotal()
Public class PayItemList
Friend Property Parent as Pay
Public Class PayIteLineItem
Public Property Total
Ctype(Me.parent, PayIteLineItemList).Parent.UpdateTotal()
Public Class PayIteLineItemList
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: mwaped
[mailto:cslanet@lhotka.net]
Sent: Sunday, October 12, 2008 7:38 AM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] RE: RE: Totals and collections
Sergey,
I still need your help
Copyright (c) Marimer LLC