vb.netclasseventsdictionaryraiseevent

Trying to fire events from a Class that is within a Dictionary instantiated on the MainForm


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?


Solution

  • 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.