Events propagation


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 2 of 2

Thread: Events propagation

  1. #1
    Join Date
    Sep 2005
    Posts
    1

    Question 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

  2. #2
    Join Date
    Nov 2003
    Location
    Alameda, CA
    Posts
    1,737
    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

  1. Replies: 0
    Last Post: 02-20-2005, 02:06 PM
  2. ASP.NET Community Events Calendar
    By ASPSmith Training in forum dotnet.announcements
    Replies: 0
    Last Post: 06-14-2002, 08:39 PM
  3. COM Interop and Events.
    By Dave in forum .NET
    Replies: 0
    Last Post: 05-15-2002, 10:21 AM
  4. Com+ Events
    By Faisal in forum VB Classic
    Replies: 0
    Last Post: 10-18-2000, 02:47 AM
  5. COM+ Events in NT 4.0
    By Brian in forum VB Classic
    Replies: 1
    Last Post: 06-14-2000, 05: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
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center