-
Events propagation
I have a CWorkflow class, containing a Cenclosures class, which is a collection class of CEnclosure items.
CEnclosure fires a GotDirty event when an enclosure's property is changed.
Cenclosures catches the CEnclosure.GotDirty event and fires another GotDirty event; it fires a GotDirty event
even when a new enclosure is added or an existing one is deleted.
Cworkflow catches the CEnclosures.GotDirty event and fires another GotDirty event; it fires a GotDirty event
even when a workflow's property is cahnged.
My main form catches the CWorkflow.GotDirty event and displays a message box.
This menas that in the form, if I create a workflow object, I change one of its property, then I add an
enclosure and I change one of the enclosure's property, 4 message boxes should appear: one when changing the
workflow's property; two when adding an enclosure (because I create a new enclosure and set its property and
ebcause the collection class is changed) and one when changing a property of the just added enclosure.
The problem is hat I get only 3 message boxes, because the last one is missing, that is no event if fired/caught
when changing a property of the just added enclosure.
Code follows...
Code:
------------------------------------------------------
'CEnclosure
------------------------------------------------------
Option Explicit
Public Event GotDirty()
Private mReference As String
Public Property Let Reference(Value As String)
mReference = Value
RaiseEvent GotDirty
End Property
Public Property Get Reference() As String
Reference = mReference
End Property
Private Sub Class_Initialize()
mReference = ""
End Sub
------------------------------------------------------
'CEnclosures
------------------------------------------------------
Option Explicit
Implements IUnknown
Public Event GotDirty()
Private mCol As Collection
Private WithEvents newENC As CEnclosure
Public Property Get NewEnum() As IUnknown
Set NewEnum = mCol.[_NewEnum]
End Property
Public Property Get Item(IndexKey As Variant) As CEnclosure
Set Item = mCol(IndexKey)
End Property
Public Property Get Count() As Long
Count = mCol.Count
End Property
Public Sub Remove(IndexKey As Variant)
mCol.Remove IndexKey
RaiseEvent GotDirty
End Sub
Public Function Add(Index As Integer, Reference As String) As CEnclosure
Set newENC = New CEnclosure
newENC.Reference = Reference
If mCol.Count = 0 Then
mCol.Add newENC
ElseIf Index > mCol.Count Then
mCol.Add newENC, , , mCol.Count
Else
mCol.Add newENC, , Index
End If
RaiseEvent GotDirty
Set Add = newENC
Set newENC = Nothing
End Function
Private Sub Class_Initialize()
Set mCol = New Collection
End Sub
Private Sub Class_Terminate()
Set mCol = Nothing
End Sub
Private Sub newENC_GotDirty()
RaiseEvent GotDirty
End Sub
------------------------------------------------------
'CWorkflow
------------------------------------------------------
Option Explicit
Public Event GotDirty()
Private WithEvents mENC As CEnclosures
Private mInfo As String
Public Property Let Info(Value As String)
mInfo = Value
RaiseEvent GotDirty
End Property
Public Property Get Info() As String
Info = mInfo
End Property
Public Property Get Enclosures() As CEnclosures
Set Enclosures = mENC
End Property
Private Sub Class_Initialize()
mInfo = ""
Set mENC = New CEnclosures
End Sub
Private Sub Class_Terminate()
Set mENC = Nothing
End Sub
Private Sub mENC_GotDirty()
RaiseEvent GotDirty
End Sub
------------------------------------------------------
'FORM
------------------------------------------------------
Option Explicit
Dim WithEvents w As CWorkflow
Private Sub Command1_Click()
Dim el As CEnclosures
Dim e As CEnclosure
Set w = New CWorkflow
w.Info = "Info" 'Here 1 message box is displayed since one event is fired from CWorkflow
Set el = w.Enclosures
Set e = el.Add(3, "Enclosur") 'Here 2 message boxes are displayed
'since 2 events are fired: one from CEnclosure and
'one from CEnclosures
e.Reference = "Enclosure" 'Here 1 message box should be displayed but it is not
'because no event is fired
End Sub
Private Sub w_GotDirty()
MsgBox "GotDirty"
End Sub
-
I believe this is what is happening.
In CEnclosures, you declare a CEnclosure with events, and you add it to the collection. But then you set it to nothing, so at this points the object still exists because it is still referenced by the Collection, but has lost the Sync interface that allows the event to be fired.
In situations like this (it is the same in an array of objects, not only a Collection) one solution is to add an extra class that raises the event, and pass it around:
CEventSync code:
Public event MyEvent()
public sub RaiseMyEvent()
raiseevent MyEvent
end sub
Create one instance withevents of this class in CEnclosures:
private withevents m_c as CEventSync
private sub m_c_MyEvent()
raiseevent GotDirty
end sub
and pass this class to each of the created CEnclosure objects. In CEnclosure, keep a reference of this class in a private variable then, instead of raising the event, call the RaiseMyEvent method of this new class.
This is just one method, and it is the one I prefer because it does not create any circular reference and does not need any global object.
Hope this is clear, please let me know
Marco
"There are two ways to write error-free programs. Only the third one works."
Unknown
Similar Threads
-
By Prometheus in forum Java
Replies: 0
Last Post: 02-20-2005, 01:06 PM
-
By ASPSmith Training in forum dotnet.announcements
Replies: 0
Last Post: 06-14-2002, 07:39 PM
-
Replies: 0
Last Post: 05-15-2002, 09:21 AM
-
By Faisal in forum VB Classic
Replies: 0
Last Post: 10-18-2000, 01:47 AM
-
By Brian in forum VB Classic
Replies: 1
Last Post: 06-14-2000, 04:55 PM
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
Forum Rules
|
Top DevX Stories
Easy Web Services with SQL Server 2005 HTTP Endpoints
JavaOne 2005: Java Platform Roadmap Focuses on Ease of Development, Sun Focuses on the "Free" in F.O.S.S.
Wed Yourself to UML with the Power of Associations
Microsoft to Add AJAX Capabilities to ASP.NET
IBM's Cloudscape Versus MySQL
|
Bookmarks