尝试从 MainForm 上实例化的字典中的 Class 触发事件

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

当此 class 在词典中时,尝试在 MainForm 中接收在 class 中引发的事件。这里有一些代码示例。

创建了 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

结束Class

在 FormMain 代码中我们有:

    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

如何使用作为字典一部分的 class 设置事件?

在我得到答案之前有几处错误。编写您自己的事件签名不是一个好主意。你应该使用 EventName(Sender As Object, e As ZoneEventArgs)。如果您发现还需要其他东西,您只需要将它添加到 EventArgs class 而不是重构代码块。为此:

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))

现在if/when你运行 CA,它不会骂你...至少不会。

在 FormLoad 中声明 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

您还应该有一个 RemoveZoneDropZone 方法,其中从集合中删除区域并 RemoveHandler 用于解除处理程序。

一个更好的方法是写一个集合class。这将处理创建区域项目、在本地捕获事件并执行 DictionaryKey 的角色以便您可以找到它们。然后,当它捕获其中一个事件时,它会为表单或其他侦听器引发类似的事件。

这是一种更加灵活的方法,可以从表单中获取所有与区域相关的代码。有了字典,就没有什么可以阻止来自 adding/removing 项的其他代码 - 使用集合 class 的 OO 方法会。