Home All Groups Group Topic Archive Search About
Author
19 Sep 2005 9:24 AM
thegios
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...


------------------------------------------------------
'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

Author
19 Sep 2005 1:36 PM
Larry Serflaten
"thegios" <theg***@discussions.microsoft.com> wrote
> 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.
<...>
> 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.


It is missing because you do not have anyone listening when the event is raised.



> Public Function Add(Index As Integer, Reference As String) As CEnclosure
< ... >        
>     Set Add = newENC
>     Set newENC = Nothing
> End Function

Note here that you set newENC to Nothing, so it no longer will be listening
for events.

Typically, if you want to raise an event from many child objects to a single
parent object, you'd do that using a third object that you can pass to all
the child objects.  Each child then has a reference to the same object
delegated to raising events, and the parent only needs to listen for events
from that one delegated object.  A simple example follows:

Uses 4 modules:
    TYPE   NAME
    Form    Form1
    Class    Parent
    Class    Child
    Class    Delegate

' [  Form1  ]

Option Explicit
Private WithEvents Mom As Parent

Private Sub Form_Load()
Set Mom = New Parent
Dim Sue As Child
Dim Ted As Child
Dim Pat As Child

  Set Sue = Mom.Create("Sue", 12)
  Set Ted = Mom.Create("Ted", 10)

  Set Pat = New Child
  Pat.Name = "Pat"
  Pat.Age = 8
  Mom.Add Pat         ' Event raised from parent

  Pat.Name = "Patty"  ' Event raised from child
  Sue.Age = 13        ' Event raised from child

End Sub

Private Sub Mom_Shouting(Kid As Child, Msg As String)
  Debug.Print Kid.Name, Msg
End Sub



' [  Parent  ]

Private Kids As New Collection
Private WithEvents ChildControl As Delegate

Public Event Shouting(Kid As Child, Msg As String)

Public Sub Add(Kid As Child)
  Kids.Add Kid
  Set Kid.Control = ChildControl
  RaiseEvent Shouting(Kid, "Added to collection.")
End Sub

Public Function Create(Name As String, Age As Long) As Child
  Set Create = New Child
  Create.Name = Name
  Create.Age = Age
  Set Create.Control = ChildControl
End Function

Private Sub ChildControl_Shouting(Kid As Child, Msg As String)
  RaiseEvent Shouting(Kid, Msg)
End Sub

Private Sub Class_Initialize()
  Set ChildControl = New Delegate
End Sub


' [  Child  ]

Public Control As Delegate

Private mName As String
Private mAge As Long

Public Property Get Name() As String
  Name = mName
End Property

Public Property Let Name(ByVal NewName As String)
  If NewName <> mName Then
    mName = NewName
    ReportBack "Name change."
  End If
End Property

Public Property Get Age() As Long
  Age = mAge
End Property

Public Property Let Age(ByVal NewAge As Long)
  If NewAge <> mAge Then
    mAge = NewAge
    ReportBack "Age change."
  End If
End Property

Private Sub ReportBack(Msg As String)
  If Not Me.Control Is Nothing Then
    Me.Control.Shout Me, Msg
  End If
End Sub



' [  Delegate  ]

Public Event Shouting(Kid As Child, Msg As String)

Public Sub Shout(Kid As Child, Msg As String)
  RaiseEvent Shouting(Kid, Msg)
End Sub