We help IT Professionals succeed at work.

VB.NET Event not Being Handled

Hello Experts,

I am just dipping into custom events and have hit a major snag. An event raised in one class is not being handled when another class initiates the sub that contains the event. I have attached my code. All help is greatly appreciated.
Public Class ResultCollection
        Inherits CollectionBase
        Public Event ResultLoaded(ByVal CurrentRecord As Integer, ByVal TotalRecords As Integer)
        Default Public Overridable ReadOnly Property Item(ByVal index As Integer) As Result
            Get
                Return CType(Me.List(index), Result)
            End Get
        End Property

        Public Sub Add(ByVal Result As Result)
            List.Add(Result)
        End Sub
        Public Sub New()

        End Sub
        Public Sub New(ByVal CycleCountCompletionID As Integer)
            Dim CurrCount As Integer = 0
            Dim TotalRecords As Integer = 0

            Dim SQL As String = [OMITTED]
            Dim DS As DataSet = VSMS.GetDataSet(SQL, VSMS.TRIPConnStr)
            TotalRecords = DS.Tables(0).Rows.Count

            For Each DR As DataRow In DS.Tables(0).Rows
                CurrCount += 1
                Me.Add(New Result(Convert.ToInt32(DR.Item("CycleCountResultID"))))
                RaiseEvent ResultLoaded(CurrCount, TotalRecords) '<-- EVENT FIRES HERE AND IS HANDLED PROPERLY IF I ADD AN EVENT HANDLER TO THE SAME CLASS
            Next

        End Sub



    End Class

Public Class Completion
        Private WithEvents _Results As New ResultCollection

        Public Sub LoadResults()

            _Results = New ResultCollection(CycleCountCompletionID) '<--This SHOULD get the event handler to start firing events.

        End Sub
        
Public Sub _Results_ResultLoaded(ByVal CurrentRecord As Integer, ByVal TotalRecords As Integer) Handles _Results.ResultLoaded
'EVENT SHOULD BE RAISED HERE, BUT DEBUGGING SHOWS THAT IT IS NOT HITTING THIS SUB.
            Dim X As String = ""
        End Sub
End Class

Open in new window

Comment
Watch Question

Public Class ResultCollection
        Inherits CollectionBase
        Public Event ResultLoaded(ByVal CurrentRecord As Integer, ByVal TotalRecords As Integer)
        Default Public Overridable ReadOnly Property Item(ByVal index As Integer) As Result
            Get
                Return CType(Me.List(index), Result)
            End Get
        End Property

        Public Sub Add(ByVal Result As Result)
            List.Add(Result)
        End Sub
        Public Sub New()

        End Sub
        Public Sub New(ByVal CycleCountCompletionID As Integer)
            Dim CurrCount As Integer = 0
            Dim TotalRecords As Integer = 0

            Dim SQL As String = [OMITTED]
            Dim DS As DataSet = VSMS.GetDataSet(SQL, VSMS.TRIPConnStr)
            TotalRecords = DS.Tables(0).Rows.Count

            For Each DR As DataRow In DS.Tables(0).Rows
                CurrCount += 1
                Me.Add(New Result(Convert.ToInt32(DR.Item("CycleCountResultID"))))
                RaiseEvent ResultLoaded(CurrCount, TotalRecords) '<-- EVENT FIRES HERE AND IS HANDLED PROPERLY IF I ADD AN EVENT HANDLER TO THE SAME CLASS
            Next

        End Sub



    End Class

Public Class Completion
       ' This is the correct statement
       Private WithEvents _Results As ResultCollection
' The Error Go Here ... No Need for the "New" Keyword ' Private WithEvents _Results As New ResultCollection
        Public Sub LoadResults()

            _Results = New ResultCollection(CycleCountCompletionID) '<--This SHOULD get the event handler to start firing events.

        End Sub
       
Public Sub _Results_ResultLoaded(ByVal CurrentRecord As Integer, ByVal TotalRecords As Integer) Handles _Results.ResultLoaded
'EVENT SHOULD BE RAISED HERE, BUT DEBUGGING SHOWS THAT IT IS NOT HITTING THIS SUB.
            Dim X As String = ""
        End Sub
End Class
Commented:
from help on Raiseevent statement from BOL,
http://msdn.microsoft.com/en-us/library/fwd3bwed(VS.80).aspx

Non-shared events should not be raised within the constructor of the class in which they are declared. Although such events do not cause run-time errors, they may fail to be caught by associated event handlers. Use the Shared modifier to create a shared event if you need to raise an event from a constructor.


So in your case either change the event to be a shared member or change the place from where you are raising the event.

to change to shared event,
Public Event ResultLoaded(ByVal CurrentRecord As Integer, ByVal TotalRecords As Integer)
to
Public Shared Event ResultLoaded(ByVal CurrentRecord As Integer, ByVal TotalRecords As Integer)


Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
Top Expert 2009
Commented:
It's because the "work" is being done from the constructor.

You need to break it out so that the work is in another sub and call it after instantiation.

Try this example out to see the difference:
Public Class Form1

    Private WithEvents cntWrong As CounterWrong
    Private WithEvents cntCorrect As CounterCorrect

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        cntWrong = New CounterWrong(5)

        cntCorrect = New CounterCorrect(5)
        cntCorrect.StartCount()
    End Sub

    Private Sub cntWrong_Count(ByVal i As Integer) Handles cntWrong.Count
        Debug.Print("cntWrong: " & i)
    End Sub

    Private Sub cntCorrect_Count(ByVal i As Integer) Handles cntCorrect.Count
        Debug.Print("cntCorrect: " & i)
    End Sub
End Class

Public Class CounterWrong

    Public Event Count(ByVal i As Integer)

    Public Sub New(ByVal CountTo As Integer)
        For i As Integer = 1 To CountTo
            RaiseEvent Count(i)
        Next
    End Sub

End Class

Public Class CounterCorrect

    Private _CountTo As Integer

    Public Event Count(ByVal i As Integer)

    Public Sub New(ByVal CountTo As Integer)
        _CountTo = CountTo
    End Sub

    Public Sub StartCount()
        For i As Integer = 1 To _CountTo
            RaiseEvent Count(i)
        Next
    End Sub

End Class

Open in new window

Commented:
but be careful with using shared events. behaviour may change in case you use multiple instances of the class.

Author

Commented:
Thanks to the excellent information from appari and Idle_Mind I was able to solve this problem in less than 5 minutes. Thanks a bunch!