
Raising events from collection member objects?!?!
You're right to want to use events from collections. All sophisticated
object models support them.
An approach that I've used is as follows:
-- First, use collection classes. Let's assume that your CCustomer object
owns a collection of orders. A variable of type COrders would be declared
WithEvents in the CCustomer object. The COrders collection would support the
standard collection methods and properties, including Add, Item (the
default), Count and Remove. In addition:
-- Add a friend method to the COrders collection class --
RaiseEvent(EventKey As Long, Item As Variant). EventKey will identify
which event you'd like to raise, Item can either hold a reference to the
item raising the event, or the item's key. Use a select case to raise the
appropriate event.
-- Add a public event to the class for each event you'd like your individual
objects to support. If the items need to support a DataChanged event, for
example, add a public event to the collection: DataChanged(Item as Variant).
-- Add a friend property to the COrder object (the individual item in the
collection) that allows you to pass a reference to the parent collection
when the new COrder is added to it. Typically, I call this the Parent
property.
-- When new items are added to the COrders collection (in the COrders.Add
method) set the Parent property of the new COrder = me.
-- In the COrder, when you need to raise an event, just call
Parent.RaiseEvent, passing the correct EventKey and either a reference to
the COrder or its index.
Since the COrder holds a reference to COrders, be sure that when you want to
get rid of that object, you release the reference to COrders, otherwise
COrder's Class_Terminate will never fire and you'll get memory leaks. I'd
add a friend Destroy method to the COrder, which I call before setting the
reference to nothing. Also, add a Friend Destroy method to the collection,
which calls Destroy on the items before removing them.
In a recent project, where I was dealing with around 50 different
collections, I found it much easier to create a generic IEventMgr interface,
which was implemented in all the collections. That way, each child object's
Parent property was of type IEventMgr, not COrders or CItems or whatever,
and the code in the items could be copied without worrying about changing
the declarations.
Let me know if you'd like some examples.
David E. Hirshfield, MCSD
Quote:
> A different approach would be not to have events at all, but rather have a
> public procedure in a module that is called from the class. Your class
> would need to have something like a strKey property that you set when
adding
> to your array or collection, and that strKey property is passed to the
code
> modules procedure as one of the arguements.
> --
> Bill McCarthy, MVP VB
> Total Environment
> www.TotalEnviro.com/PlatformVB
> > I recently posted a question about how to raise an event from an object
> > referenced by a collection. The response I got was:
> > Have the objects stored in the collection raise an event. This event
> would
> > include the object's key, or index in the event's argument list. You'd
> have
> > to store that in an object property. Declare the objects in the
"client"
> > (or event sink) object/form "With Events". Code an event handler for
this
> > in the client/sink object. That event handler would use the key or
index
> to
> > differentiate the collections constituent objects.
> > This is helpful, but the problem with this solution is that the event
only
> > gets raised when an object variable (other than the collection) that was
> > declared "WithEvents" is referring to the object that raises the event
at
> > the time the event is raised. This is obviously a problem because I
can't
> > predict which object will raise an event at any given time, and neither
> can
> > I reasonably maintain individual object variables for each of the n
> objects
> > I've created. That's the purpose of the collection; to maintain
> references
> > to an indeterminate number of objects. So, the problem remains: If I
> > create n objects, add them to a collection, and maintain the collection
as
> > my only reference to the objects created, is there any way to intercept
> > events raised by objects that are members of the collection. Again, I
> want
> > the objects in the collection to raise events much the same way controls
> in
> > a control array raise events. Also, I'm not stuck on using a
collection;
> if
> > there's a way to do this using arrays or some other structure, I'd love
to
> > hear about it.
> > Obviously I can't have this:
> > private withevents object_1 as class1
> > private withevents object_2 as class1
> > private withevents object_3 as class1
> > ...
> > private withevents object_n as class1
> > Thanks for anyone's help with this. Please respond even if you know
this
> > cannot be done because it'll save me the time of wondering if there's a
> way
> > to do it.
> > Dave Clipsham
> > Bloomfield & Grossart, Inc.