Events Support???

L

Lance Marrano

I have a class which has events, and I have declared an instance of this
class as "withevents" on my form. Consequently, the variable shows properly
in code view, and the events are properly visible in the right-hand
dropdown. I have also added routines in the form to handle the event (and
they include the handles clause). But when I run my project, and these
events are raised, the form doesn't respond (based upon the breakpoints I've
sent, it doesn't even go in there). Does anyone know of any special issues
with creating and consuming custom events.
(Hopefully) TIA,
Lance Marrano
 
D

Daniel Moth

So your app is responsive but the event handler methods are never hit?
If not, then you are raising the event from a worker thread without using
Invoke.

Can you hit other breakpoints? If not, then you are in release mode.

Assuming all else is fine, post sample code so we can comment.

Cheers
Daniel
 
L

Lance Marrano

My guess is you're on to something about the worker thread....I'm afraid
I've mostly done ASP.Net programming up until now. Here's my sample code:


Public Class Importer
Public Event ImportingTable(ByVal TableName As String)
....
Public Sub SendTable(TableName as string)
....
RaiseEvent ImportingTable(TableName)
....
End Sub

And in my frmImport:
In the class declaration:
Dim oImp as Importer
....
Private Sub oImp_ImportingTable(TableName as string) handles
oImp.ImportingTable
Label.Text = "Importing " + TableName
End Sub
....
End Class

Hopefully that will help you tell me what I'm doing wrong (and yes I can hit
other breakpoints).

Thanks,
Lance Marrano
 
D

Daniel Moth

Dim oImp as Importer

should be

Dim WithEvents oImp as Importer

The worker thread issue would be relevant if your app froze (it would happen
if your SendTable method was called from another thread).

Cheers
Daniel
 
D

Daniel Moth

Well, typos or not, you are not showing the relevant code. Where does
SendTable get called from? Post a small reproducible sample.

Cheers
Daniel
 
L

Lance Marrano

Thanks for your patience. Here's the appropriate snippets (I believe this
will have the full necessary code).
Since it's not shown, and maybe it make a difference, frmImport is opened
from frmMain using ShowDialog (hence why the return value is set).
-----------------------------------------------------------------------------------------------------------
Public Class frmImport

Private WithEvents oImp As Importer_ADOCE

Private Sub cmdImport_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles cmdImport.Click

Me.lblInstructions.Enabled = False

Me.txtFileLocation.Enabled = False

Me.cmdOpen.Enabled = False

Me.lblDivider.Visible = True

Me.StatusLabel.Visible = True

Me.lblStatus.Visible = True

Me.prgbrStatus.Visible = True

Me.Refresh()

'begin the import with the path

Dim oImp As Importer_ADOCE

oImp = New Importer_ADOCE(txtFileLocation.Text)

If oImp.Import = True Then

'close the form and refresh the tree

MessageBox.Show("Import Successfull")

Me.DialogResult = Windows.Forms.DialogResult.OK

Me.Close()

End If

End Sub

Private Sub cmdOpen_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles cmdOpen.Click

Me.OpenFileDialog1.Filter = "BRED database (*.cdb)|*.cdb"

If Me.OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then

Me.txtFileLocation.Text = Me.OpenFileDialog1.FileName

Me.cmdImport.Enabled = True

End If

End Sub

Private Sub oImp_ImportingTable(ByVal TableName As String) Handles
oImp.ImportingTable

Me.lblStatus.Text = "Importing " & TableName

Me.Refresh()

End Sub

End Class

-----------------------------------------------------------------------------------------------------
Imports InTheHand.Data.Adoce

Public Class Importer_ADOCE

Inherits Importer

''' <summary>

''' Raised by the inheriting class when starting to import a new table

''' </summary>

''' <param name="TableName"></param>

''' <remarks></remarks>

Public Event ImportingTable(ByVal TableName As String)

Private strFile As String

Private cnADOCE As AdoceConnection

Sub New(ByVal SourceFile As String)

strFile = SourceFile

End Sub

Public Function Import() As Boolean

'open the connection to the source and transfer each table

Try

cnADOCE = New AdoceConnection(strFile)

cnADOCE.Open()

SendTable("Organization")

SendTable("Group")

SendTable("Hierarchy")

SendTable("Facility")

SendTable("Group_Facilities")

SendTable("Sample_Location")

SendTable("Building")

SendTable("Building_System")

SendTable("System_Component")

SendTable("Section")

SendTable("SectionDetails")

SendTable("Inspection_Data")

'SendTable("Sample_Data")

'SendTable("Sample_Subcomponent")

'SendTable("Sample_Subcomp_Distress")

Return True

Catch ex As Exception

Return False

Finally

If Not cnADOCE Is Nothing Then

If cnADOCE.State <> Data.ConnectionState.Closed Then

cnADOCE.Close()

End If

cnADOCE.Dispose()

End If

End Try

End Function

Public Sub SendTable(ByVal TableName As String)

Dim dr As AdoceDataReader

Try

RaiseEvent ImportingTable(TableName)

dr = New AdoceCommand("SELECT * FROM " & TableName, cnADOCE).ExecuteReader()

MyBase.TransferTable(TableName, dr)

Finally

If Not dr Is Nothing Then

If Not dr.IsClosed Then

dr.Close()

End If

dr.Dispose()

End If

End Try

End Sub

End Class

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

Public MustInherit Class Importer

Private dsBRED As New Data.DataSet

''' <summary>

''' Copy the source table to the BRED database

''' </summary>

''' <param name="TableName"></param>

''' <param name="SourceReader"></param>

''' <remarks></remarks>

Protected Sub TransferTable(ByVal TableName As String, ByVal SourceReader As
Data.IDataReader)

Dim da As Data.SqlServerCe.SqlCeDataAdapter

Dim dc As Data.SqlServerCe.SqlCeCommand

Dim cb As Data.SqlServerCe.SqlCeCommandBuilder

Dim nr As Data.DataRow

Try

'erase the existing table data

dc = New Data.SqlServerCe.SqlCeCommand("DELETE FROM " & TableName,
Connection)

dc.ExecuteNonQuery()

'now fill

da = New Data.SqlServerCe.SqlCeDataAdapter("SELECT * FROM " & TableName,
Connection)

cb = New Data.SqlServerCe.SqlCeCommandBuilder(da)

da.Fill(dsBRED, TableName)

Do While SourceReader.Read

nr = dsBRED.Tables(TableName).NewRow()

For i As Integer = 0 To dsBRED.Tables(TableName).Columns.Count - 1

nr.Item(i) = SourceReader.Item(i)

Next

dsBRED.Tables(TableName).Rows.Add(nr)

'this will keep the number of rows in the dataset low,

'therefore keeping the memory low

If dsBRED.Tables(TableName).Rows.Count > 100 Then

da.Update(dsBRED.Tables(TableName))

dsBRED.Tables(TableName).Rows.Clear()

End If

Loop

da.Update(dsBRED.Tables(TableName))

'remove the table to save memory

dsBRED.Tables.Remove(TableName)

Catch ex As Exception

End Try

End Sub

End Class
 
L

Lance Marrano

As a strange followup, I added a line to manually add the event handler and
it worked! So why doesn't declaration with WithEvents not work?

Here's what I changed (see previous post to compare) in frmImport:
Private Sub cmdImport_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles cmdImport.Click

Me.lblInstructions.Enabled = False

Me.txtFileLocation.Enabled = False

Me.cmdOpen.Enabled = False

Me.cmdImport.Enabled = False

Me.lblDivider.Visible = True

Me.StatusLabel.Visible = True

Me.lblStatus.Visible = True

Me.prgbrStatus.Visible = True

Me.Refresh()

'begin the import with the path

Dim oImp As Importer_ADOCE

oImp = New Importer_ADOCE(txtFileLocation.Text)

' the next line is new

AddHandler oImp.ImportingTable, AddressOf Me.oImp_ImportingTable

If oImp.Import = True Then

'close the form and refresh the tree

MessageBox.Show("Import Successfull")

Me.DialogResult = Windows.Forms.DialogResult.OK

Me.Close()

End If

End Sub
 
D

Daniel Moth

I think I just realised what you are doing.

You have declared two different variables of different scope of the same
type with the same name (oImp). In your first example you were attaching an
event handler (via WithEvents) to one variable and were expecting it to be
called as a result of an action on the other variable. In your second
example, you ignore the first variable altogether and do the correct thing
with the second variable (via AddHandler).

Why do you have oImp at the class level (Private WithEvents oImp) and also
in the method (Dim oImp) ?

Cheers
Daniel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top