Problem monitoring PropertyChanged within business objects

Problem monitoring PropertyChanged within business objects

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


hurcane posted on Friday, May 04, 2007

I am having a problem with event handling among a set of business objects. I have a few different ideas for how to resolve it, but I am hoping somebody else may have dealt with a similar scenario and can stop me from going down the path of destruction. I also don't want to spend a lot of time trying two solutions that ultimately won't work before I try the one that will work. :-)

My use case is an order entry situation. The order entry process allows the sales rep to create new inventory SKUs. The UI includes a "new inventory" panel within the order line maintenance form. This panel binds to a set of "new inventory" objects.

An order could use the same SKU on multiple lines of a single order. When the order line is using a new SKU, we have to ensure that the user sees the same information on each detail line. To meet this requirement, we are keeping a list of the "new inventory" objects in the order object. Order lines have a reference to the order object, through which they retrieve the "new inventory" objects.

The order line and the "new inventory" object also synchronize with each other. Some properties that are edited on the "new inventory" object are copied to all the order lines on the order when they are changed. We meet this requirement in the order line by handling the PropertyChanged event of the "new inventory" object.

This complex relationship has gotten me into a circular situation that is my core problem. The problem happens when we remove order lines that were referencing a "new inventory" object. We needed a way to remove unused new inventory items because they are part of the IsValid logic, and we can't save the order if they were incomplete when the line was removed. Because the "new inventory" object might be shared, we can't simply remove it when the order line is removed.

I have code in IsValid to remove the unused "new inventory" objects from the order before checking the collection's IsValid property. The problem is that the removed line is still in memory and holding a reference to these objects. When the "new inventory" object is removed from the collection, it fires OnUnknownPropertyChanged. This triggers code in the removed order line that causes the line to reference one of the other "new inventory" objects, which adds it back into the order header.

I've tried changing the order of how I remove the objects, but I've got such a complex relationship that I can't get all the objects deleted.

How can I solve this?

My first hack idea is to put a class level boolean variable in the order object that is set while I'm cleaning up the "new inventory" objects. The methods that return the "new inventory" objects will return nothing if they get a request while the boolean variable is set. This doesn't smell good to me.

Another option is to override OnUnknownPropertyChanged within the "new inventory" objects. I could have it not do anything. This would solve my problem with removed lines, but I'm afraid it will break the databinding of the panel in other scenarios.

A third option is to not use the PropertyChanged events, but to create custom events for the properties that need to be handled internally. I'll have to raise two events when the properties change.

Finally, I could try to find a way to unhook the event handlers when the order line is removed. I could put a Friend sub on the order line (OnRemoval) that is called by the collection when it is removing the order line.

Any other suggestions or recommendations?

RockfordLhotka replied on Friday, May 04, 2007

It seems to me that the rules for removing a new SKU are that there are no consumers for it. You could use a form of reference counting for each SKU.

As each line item associates itself with a new SKU, increment a counter. As each line disassociates itself with a new SKU (because the user changed the SKU on the line, or removed the line) decrement the counter.

This requires that each line have a reference to the new SKU it is using - which I assume already exists anyway. So your SKU class just needs to implement Register() and Deregister() methods (or AddRef() and ReleaseRef() or whatever) to allow the inc/dec operation.

If a SKU sees its counter hit zero in the Deregister() method, it can remove itself from its parent list by calling IParent.RemoveChild() (assuming you are using a BLB to contain the new SKUs).

hurcane replied on Saturday, May 05, 2007

Rocky,

I have considered reference counting as well, but there is a small problem with your suggested solution, as I understand it. You say "as each line disassociates itself". I am handling the changed SKU, but the lines currently have no knowledge they are being removed. They are being removed through their parent collection. The UI calls the remove method of the order line collection, passing in a reference to the order line.

Am I missing something? I looked for an overridable method that the child could use when it was being removed from the collection, but I couldn't find that.

Copyright (c) Marimer LLC