Umm good pickup Martin ;)
In my app I have been doing
SetPropertyValue("_createdOn", _CreatedOn, DateTime.Now)
OnChanged("CreatedOn")
before this discussion I thought the first parameter of the SetPropertyValue actually required the "name" of the member you were setting (as I thought XPO was using Reflection to find the member), it was only during this discussion that I thought about it more and realised that if indeed XPO is using Reflection to pull up the member that would have to be woefully slow, it was then that I realised the "string" propertyname was just used for the "OnChanged' part, hence I mentioned you could just have that for your notification (without giving it much more thought)
you are however right and the previous way I have done it would be "valid" in what we are doing in the OnChanged to do update tracking.
In regard to the GrossProfit and why to call OnChanged, the reason here is Binding, Binding updates on property changes so the issue is if you change a "source" property such as cost or sell you won't see it reflected in your control that is bound to grossprofit as the "bindingmanager thingy" hasn't been told there was a change to GrossProfit. So this is more for a fully compatable object that will work as expected when bound.
From memory I think XAF has some "ImmediatePost" or something that I believe does something like this also but I would still put the OnChanged("GrossProfit") in both CostPrice and SellPrice.
With your example of ContactKindInfo I do something a little "different" here, I only update this field when the child object changes something that would "affect' my parent object.
So I will assume your Parent Class in your example is Contact and the Children are ContactKind
In the Contact constructor I place
addhandler LinkedContactKinds.CollectionChanged, AddressOf LinkedContactKinds_CollectionChanged
and in the Finalize event of the object I place
removehandler LinkedContactKinds.CollectionChanged, AddressOf LinkedContactKinds_CollectionChanged
my method that handles the event looks like
Private Sub LinkedContactKinds_CollectionChanged(ByVal sender As Object, ByVal e As XPCollectionChangedEventArgs)
If e.CollectionChangedType = XPCollectionChangedType.AfterAdd Or e.CollectionChangedType = XPCollectionChangedType.AfterRemove Then
UpdateContactKinds()
End If
End Sub
then in my ContactKind class I would have like in your case the Name property affects your "Parent" class so in the Name Property I would have
If not IsLoading() and Contact IsNot Nothing then
Contact.UpdateContactKinds()
end if
then all I would have in your Contact class
<persistent()> _
<Size(25)> _
private _contactKindInfo as String
Public ReadOnly Property ContactKindInfo as String
Get
return _contactKindInfo
End Get
End Property
Public Sub UpdateContactKindInfo()
dim infostring as string = String.Empty
if LinkedContactKinds.Count > 0)
for each item as ContactKind in LinkedContactKinds
infostring &= String.Format("{0} ", item.Name.Substring(0, 1))
next
end if
SetPropertyValue("_contactKindInfo", _contactKindInfo, infostring)
End Sub
So with that basically if something changes your "ContactKindInfo" will be "updated", but in general will be "left" alone. and because the OnChanged still occurs it is safe.
Just some food for thought