1

Trying to have events raised within a class be received within the MainForm when this class is within a Dictionary. Here are some code samples.

Created a Class:

Public Class Zone
Public _ZoneID As Integer
Public _ZoneName As String

Public Event ZoneEntered(ByVal intToolID As Integer, ByVal intZoneID As Integer)

Public Sub New()

End Sub

Public Property ZoneName() As String
    Get
        Return _ZoneName
    End Get
    Set(value As String)
        _ZoneName = value
    End Set
End Property

Public Property ZoneID() As Integer
    Get
        Return _ZoneID
    End Get
    Set(value As Integer)
        _ZoneID = value
    End Set
End Property

Public Sub CheckZone(ByVal intToolID As Integer)
    If intToolID > 0 Then
        RaiseEvent ZoneEntered(intToolID, _ZoneID)
    End If
End Sub

End Class

Within the FormMain code we have:

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim Zones As New Dictionary(Of Integer, Zone) 'Holds all the Zones for all CameraGroups within this Workspace

    Dim NewZone As Zone
    NewZone.ZoneName = "TestZone"
    NewZone.ZoneID = 123
    Zones.Add(1, NewZone)

    Dim intZoneID As Integer = 1
    If Zones.ContainsKey(intZoneID) Then
        Dim ZoneActive As Zone
        ZoneActive = Zones(intZoneID)
        If Not (ZoneActive Is Nothing) Then
            ZoneActive.CheckZone(intZoneID) 'This would fire the event I am looking for
        End If
    End If

End Sub

How do I setup events from with the class that is part of a dictionary?

  • There is nothing there listening for events. You probably want some sort of collection class which catches the item's events, then raises its own ("bubbles up") such as `Event ZoneEntered(sender, ZoneEventArgs)` where the event args describe which zone. Otherwise your form will have to hookup an event handler for each item in the dictionary. – Ňɏssa Pøngjǣrdenlarp Jun 01 '15 at 20:53
  • oops I realized that I forget to show the code that wires up the event in the form. But that is the issue as I cant figure out how to hookup an event handler for each item in the dictionary. I am totally aware on how to do this for a basic class but when the class is in a dictionary I am stumped. – Ross Rawlings Jun 02 '15 at 01:38
  • why does it need to be an event? who is going to catch them? It looks like if `CheckZone` was a function, perhaps that returns True instead of RaiseEvent, the form could take the same action it would for an event. otherwise, as I said you need to write a collection class to forward the events for the collection items – Ňɏssa Pøngjǣrdenlarp Jun 02 '15 at 02:04
  • Thanks for the tips Plutonix but I was only outlining an example. The Zone class is actually complex doing a lot more than what is here and is part of many other classes. I am basically trying to get events fired back to the say the MainForm from many classes contained in a dictionary. I am looking for a code snippet as to how I would wire this up in the form and/or what needs to be put into the class to support this. – Ross Rawlings Jun 02 '15 at 13:01

1 Answers1

2

There are several things wrong before I can get to an answer. It is not a good idea to make up you own Event signature. You should use EventName(Sender As Object, e As ZoneEventArgs). If you discover that something else is needed in the event you just need to add it to the EventArgs class rather than refactor gobs of code. For that:

Public Class ZoneEventArgs
    Inherits EventArgs

    Public Property ToolID As Integer
    Public Property ZoneID As Integer

    Public Sub New(tool As Integer, zone As Integer)
       ToolID = tool
       ZoneID = zone
    End Sub
End Class

' event sig:
Public Event ZoneEntered(sender As Object, e As ZoneEventArgs)

' raise it:
RaiseEvent ZoneEntered(Me, New ZoneEventArgs(thisTool, thisZone))

Now if/when you run CA, it wont scold you...at least not for that.

Declaring the Dictionary in FormLoad is bad because it will only exist there, but I'll assume that is an artifact of being a demo. To keep it like that, each item added to the collection needs to be hooked up to an event handler. For that, you need there to be only one way in and one way out of the Dictionary:

Friend Sub AddZone(name As String, zID as Integer, key As Integer)

    Dim z As New Zone With {.ZoneName = name, .ZoneID = zID)
    AddHandler z.ZoneEntered, AddressOf NewZoneEntered
    Zones.Add(key, z)
End Sub  

Private Sub NewZoneEntered(sender As Object, e As ZoneEventArgs)
    ' respond
End Sub

You should also have a RemoveZone or DropZone method where the zones are removed from the collection and RemoveHandler used to unhook the handler.

A much better way is to write a collection class. This would handle creating Zone items, catch the events locally and perform the role of the DictionaryKey to you can find them. Then when it catches one of those events, it Raises a similar one for the form or other listeners.

Its a much more flexible approach and gets all the Zone related code out of the form. With the Dictionary the way it is there is, there is nothing to stop other code from adding/removing items - an OO approach using a collection class would.

Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
  • This put a smile on my face. Thanks a bunch. I did have to change your AddHandler a bit to AddHandler z.ZoneEntered, AddressOf NewZoneEntered and everything worked. You other comments have been taken in and yes the code I placed was only to show the issue not the actual use of the Zone class. I will do some digging into the Collection class as well. Thanks and well done. – Ross Rawlings Jun 02 '15 at 20:10
  • Please click the checkmark so this gets moved off the Unanswered list. Good Luck! – Ňɏssa Pøngjǣrdenlarp Jun 02 '15 at 20:14