Vba 从自定义集合类中的对象引发事件
如果一个对象包含在一个集合中,该对象是否仍能向父类引发事件 很明显,您可以告诉子类一个对父类的引用,然后在子类内调用父类内的公共方法,但是这将导致循环引用,据我所知,这将使垃圾回收器无法摆脱这两个对象 详情: 我有两个类,一个是名为clsPerson的人,另一个是名为clsPeople的自定义集合类。clsPerson有一个名为Selected的公共布尔属性。如果selected被更改,我将调用事件SelectedChange。在这一点上,我需要在clsPeople做些事情。如何在自定义集合类clsPeople中捕获事件?person类可以在People范围之外进行更改,否则我将考虑另一种解决方案Vba 从自定义集合类中的对象引发事件,vba,events,Vba,Events,如果一个对象包含在一个集合中,该对象是否仍能向父类引发事件 很明显,您可以告诉子类一个对父类的引用,然后在子类内调用父类内的公共方法,但是这将导致循环引用,据我所知,这将使垃圾回收器无法摆脱这两个对象 详情: 我有两个类,一个是名为clsPerson的人,另一个是名为clsPeople的自定义集合类。clsPerson有一个名为Selected的公共布尔属性。如果selected被更改,我将调用事件SelectedChange。在这一点上,我需要在clsPeople做些事情。如何在自定义集合类c
<<Class clsPerson>>
Private pSelected as boolean
Public Event SelectedChange()
Public Property Let Selected (newVal as boolean)
pSelected = newVal
RaiseEvent SelectedChange
End Property
Public Property Get Selected as boolean
Selected = pSelected
End Property
<<Class clsPeople>>
Private colPeople as Collection
' Item set as default interface by editing vba source code files
Public Property Get Item(Index As Variant) As clsPerson
Set Item = colPeople.Item(Index)
End Property
' New Enum set to -4 to enable for ... each to work
Public Property Get NewEnum() As IUnknown
Set NewEnum = colPeople.[_NewEnum]
End Property
' If selected changes on a person, do something
Public Sub ???_SelectedChange
' Do Stuff
End Sub
选为布尔值的私有PSP
公共事件SelectedChange()
选定的公共属性(newVal为布尔值)
pSelected=newVal
RaiseEvent Selected更改
端属性
公共属性被选为布尔值
选中=pSelected
端属性
私人收藏
'通过编辑vba源代码文件将项设置为默认界面
公共属性获取项(索引作为变量)作为clsPerson
Set Item=colPeople.Item(索引)
端属性
'将新枚举设置为-4以启用。。。各就各位
公共属性获取NewEnum()作为IUnknown
Set NewEnum=colPeople。[[u NewEnum]
端属性
'如果选定的更改发生在某个人身上,请执行某些操作
公共子系统???\u选择更改
“做事
端接头
您可以轻松地从集合中的类引发事件,问题是另一个类无法直接从同一个类的多个类接收事件
您的clsPeople
通常接收事件的方式如下:
Dim WithEvents aPerson As clsPerson
Public Sub AddPerson(p As clsPerson)
Set aPerson = p ' this automagically registers p to the aPerson event-handler `
End Sub
Public Sub aPerson_SelectedChange
...
End Sub
<<Class clsPersonsDelegate>>
Public Event SelectedChange
Public Sub Raise_SelectedChange
RaiseEvent SelectedChange
End Sub
因此,将对象设置到任何声明为with events
的变量中,会自动注册该对象,以便该变量的事件处理程序接收该对象的事件。不幸的是,一个变量一次只能保存一个对象,因此该变量中以前的任何对象也会自动取消注册
对此的解决方案(同时仍然避免COM中引用周期的问题)是为此使用共享委托
因此,您可以创建这样一个类:
Dim WithEvents aPerson As clsPerson
Public Sub AddPerson(p As clsPerson)
Set aPerson = p ' this automagically registers p to the aPerson event-handler `
End Sub
Public Sub aPerson_SelectedChange
...
End Sub
<<Class clsPersonsDelegate>>
Public Event SelectedChange
Public Sub Raise_SelectedChange
RaiseEvent SelectedChange
End Sub
这是我们的儿童班(人)。我已经用一个公共变量替换了原始事件来保存委托。我还将RaiseEvent替换为对该事件的委托方法的调用,并将对象指针传递给它自己
<<Class clsPerson>>
Private pSelected as boolean
'Public Event SelectedChange()'
' Instead of Raising an Event, we will use a delegate'
Public colDelegate As clsPersonsDelegate
Public Property Let Selected (newVal as boolean)
pSelected = newVal
'RaiseEvent SelectedChange'
colDelegate.RaiseSelectedChange(Me)
End Property
Public Property Get Selected as boolean
Selected = pSelected
End Property
这段代码对我非常有帮助。它帮助我在VBA中同时使用接口和事件。谢谢你的发帖!在将其付诸实践后,只需对其进行几处小的更正:1)可以从
clspersonsdegate
类中的方法名称中删除文本Raise\uu
。2) 需要更改clsPeople
上的colDelegate\u SelectedChange
方法,以接受clsPerson
类型的参数。另外,对于尝试此代码的其他人,clsPeople
将需要一个初始化方法来Set colPeople=New Collection
和Set colDelegate=New clspersonsdegate
@barrettnashille Thx!是的,Raise\uuu
前缀不是必须的,我只是把它当作一种风格来使用:我喜欢保持名字的清晰,这样我就总能知道引用的是哪个。巴雷特纳什维尔的评论也是如此,对我也非常有帮助。谢谢,非常感谢!