Fog Creek Software
Discussion Board




Welcome! and rules

Joel on Software

Is there a better way to do this?


I'm writing an object that contains a factory method for instantiating other objects that are then appended to a collection.  What I want, however, is to have the parent object handle events raised in the child objects.  I've managed to pull it off, but it just bugs me that I have to declare a non-instantiated object in order to access the events of the child objects.  Consider:

Public Class ClassWithEvents

    Public Event SomethingHappened(ByVal intIndex As Integer)

    Public mintIndex As Integer

    Public Sub New(ByVal intIndex As Integer)
        mintIndex = intIndex
    End Sub

    Public Sub TriggerEvent()
        RaiseEvent SomethingHappened(mintIndex)
    End Sub

End Class

Public Module Container

    Private WithEvents CWE As ClassWithEvents

    Private col As Collection

    Public Sub Main()

        Dim i As Integer = 1

        col = New Collection

        For i = 1 To 5
            col.Add(Load(i), i)
        Next

        col.Item(3).triggerevent()

    End Sub

    Private Function Load(ByVal i As Integer) As ClassWithEvents

        Dim a As ClassWithEvents

        a = New ClassWithEvents(i)

        AddHandler a.SomethingHappened, AddressOf Trigger

        Load = a

        a = Nothing

    End Function

    Sub Trigger(ByVal intIndex As Integer) Handles CWE.SomethingHappened

        MsgBox("Handled event triggered from " & intIndex)

    End Sub

End Module

A few notes: Yes, this is a module because for the purposes of the demonstration I didn't want to create another class just for the purpose of kicking off Sub Main().  I've implemented the above functionality in an actual class and it works just fine.  Also, changing 'a' to 'CWE' has no effect as long as the 'CWE = Nothing' statement remains in fn Load. 

Long and short,  it works, but it seems sloppy to declare an unused variable without which the code won't work.

Jose Bueno
Thursday, March 17, 2005

You don't have to use "Handles CWE.SomethingHappened", just leave it out and remove the CWE object.
The AddHandler function takes care of registering your eventhandler "Trigger"  with the event.

Handles is used for registering handler with events of single objects (like you tried with the CWE instance).
In your case this does not apply as you have a whole array of objects.

AddHandler is the way to go.

HTH

Geert-Jan Thomas
Friday, March 18, 2005

Ahhhh... thank you.  I was mixing it with the technique for a fixed structure then.

Jose Bueno
Friday, March 18, 2005

Are you sure you want events? ... just wondering ...

------------------------------------

public abstract class SomethingBase
{
  protected abstract void Handle();

  public void CallForHandling()
  {
      Handle();
  }
}

public class SomethingConcrete : SomethingBase
{
  protected override void Handle()
  {
      // code: do handling
  }
}

DK
Friday, March 18, 2005

The reason for events is that the handler will be responsible for doing database logging and other operations, and I wanted to not have to instantiate a database connection from within each of maybe 50 instances of the class whose event is being handled.

Jose Bueno
Monday, March 21, 2005

*  Recent Topics

*  Fog Creek Home