Custom events question

hbrems

has no clue...
Local time
Tomorrow, 00:12
Joined
Nov 2, 2006
Messages
181
Imagine a class and two forms:

- clsEmployeeWriter: dedicated to writing employees to Employees table
- frmNewEmployee: form allowing to create a new employee
- frmEmployees: contains a listbox containing all employees

What I would like to do is create a custom event in the class that raises when an employee is added to the table. I'd like to subscribe frmEmployees to that event and update the listbox when it triggers.

This is what I've come up with so far:

clsEmployeeWriter
Code:
Public Event EmployeeWritten()

Public Sub Write(Name As String)
   ... write code ...
   RaiseEvent EmployeeWritten
End sub

frmNewEmployee
Code:
Sub
   dim e as new clsEmployeeWriter
   e.Write("John McClain")
End sub

frmEmployees
Code:
private WithEvents writer As clsEmployeeWriter

private sub writer_EmployeeWritten()
   ... Update employees listbox ...
end sub

Can you advise what I'm doing wrong and what I still need?
 
Why don't you update the listbox from the Sub in frmNewEmployee? It would be much easier that way.

In any case, to do it the way you're currently attempting, it will go something like:

frmNewEmployee
Code:
Form's declarations section:
    option compare database
    option explicit

    public e as clsEmployeeWriter

Form's Load event:
    Set e = New clsEmployeeWriter

Sub for e_EmployeeWritten
    e.Write("John McClain")
frmEmployees
Code:
Form's declarations section:
     option compare database
     option explicit
 
     public xE as clsEmployeeWriter
 
Form's Load event:
     Set xE = Forms("frmNewEmploee").e
 
Sub for xE_EmployeeWritten
     ... update control ...
Obviously this means frmNewEmployee must be opened before frmEmployees
 
I don’t think you will be able to do it across two Forms that way.

As a workaround without using RaiseEvent: -

clsEmployeeWriter
Code:
Public Sub WriteName(strName As String)
    
    MsgBox strName
  
    form_frmNewEmployee.EmployeeWritten strName
  
End Sub


frmEmployees
Code:
Private Sub cmdTest_Click()
   Dim Writer As clsEmployeeWriter
   
   Set Writer = New clsEmployeeWriter
   
   Writer.WriteName "John McClain"

End Sub


frmNewEmployee
Code:
Public Sub EmployeeWritten(strThisName As String)

   MsgBox "In EmployeeWritten with ... " & strThisName
   
End Sub

I think what it would require is a public WithEvents in a standard module, which seems to be illegal.

Chris.
 
Why don't you update the listbox from the Sub in frmNewEmployee?

Because then I'm writing code that is intended for frmEmployees in frmNewEmployee. What if there are multiple forms that can display employees? I'd need to write code in frmNewEmployee to update all these forms. What if there are multiple forms that can create employees?

On the other hand, if I can have my Writer class raise an event and if I can subscribe my forms to that event they can update themselves as needed.

In summary again what I'd like to do:
1. User creates a new employee in frmNewEmployee
2. Behind the scenes class clsEmployeeWriter is called
3. EmployeeWriter writes the record and raises the event EmployeeWritten
4. frmEmployees sees the event and updates its listbox
 
I am sure you could use the timer - set your class to create some exposed value somewhere
then have a forms timer watch for such a value, as a signal to refresh something. Still awkward, as you need a way of dismissing it afterwards - without affecting other users.

so maybe your form could issue a request to the class for notification, on opening - then you could use the class to set a field (checkbox) on the calling form that it had created a record. Examine this checkbox (using the timer) and clear it after you requery the list box. You would need some structure within the class to handle all the forms requesting notification.

I believe overuse of timers can affect app performance though. Seems a lot of work - you could just have a button to requery the list box on demand.


so a hypothetical question.

can a form receive any events outside itself. (other than the timer)
 
Last edited:
Have you even tried what was proposed to you in post #2?

If you want to listen to an event coming from another module, then you need to set the object to that module's instance of the class and it will fire.

This line is the key:
Code:
Form's Load event:
     Set xE = Forms("frmNewEmploee").e
 
Have you even tried what was proposed to you in post #2?

Well, it negates what I'm trying to accomplish: let the class raise the events and opened forms will pick up on that. In your example I'm building a reference from 1 form to the next which is exactly what I would like to avoid. :)
 
It has to be set to the same instance and WithEvents is only valid in a class module :)

Not unless you hard code it in the event, which you probably don't want.
 
Why not use VbaInet’s idea and do it in a splash Form which remains open but hidden?

Since the splash Form may also have a: -
Code:
Public Sub Writer_EmployeeWritten(strName As String)

    [color=green]' "John McClain" comes in...[/color]
    MsgBox "Here in frmEmployees EmployeeWritten with " & strName

    [color=green]' "Sam Spade" goes out and gets passed to downstream events.[/color]
    strName = "Sam Spade"

End Sub

subroutine it will be serviced first and can conditionally modify any argument passed by reference.

Any downstream serviced events would then receive the modified argument and could conditionally behave differently.

Why?...I haven’t a clue but it works.


Now for some speculation…
Could the event be raised on a server across a network?
Does the event propagate across different databases?
Would all open FE’s see the event?
If so, could this be another way for a server to send messages to all open FE’s?

Chris.
 

Users who are viewing this thread

Back
Top Bottom