3

在 Visual Basic.net 中,是否可以将事件处理程序添加到 T 的列表中,以便每当更改列表时调用此事件?

例如,如果我有一个名为 Schedule 的类,并且此 Schedule 有一个 ScheduleItem 列表,我如何添加一个在此列表更改时将调用的事件?

4

2 回答 2

4

当列表更改时,有些集合会引发事件(BindingList(of T)对于一个),但这些事件仅对列表所在的类/表单可用。对于更广泛的实现,您的ScheduleClass 可以引发事件。

  1. 确保只Schedule对列表进行更改。也就是说,您List(Of T)应该是私人会员。其他对象应该通过它进行更改,以便它完全了解所有更改,以免错过任何更改。

  2. 确定什么是变更事件。添加和删​​除项目是显而易见的,但根据ScheduleItem可能.StartTime或类似属性中的内容,事件也是如此。(这实际上需要INotifyPropertyChanged在项目类上)

  3. 对于仅添加和删除,每次Schedule从内部列表中添加或删除项目时,都会引发事件以通知订阅者。

  4. 谁将消费(或获取)这些事件?形式?其他类结构?

一个简单的方法是,一旦所有更改都发生在“拥有”列表的类中,就是一个自定义事件:

Public Class Schedule
    Private MyList as List (Of ScheduleItem)

    Public Event ScheduleChanged(sender As Object, e As EventArgs)

     ...
   Public Sub AddItemToSchedule(....)
      ' I have no idea what is in a ScheduleItem....
      ...
      MyList.Add(si)
      ' the point is that if it gets added / not a dupe etc, then:
      ' tell any subscribers that the sched changed:
       RaiseEvent ScheduleChanged(Me, New EventArgs())
   End Sub

   Public Sub RemoveItem(...)
       ' do whatever to remove an item
       ' ... 
       MyList.Remove(si)
       ' tell subscribers the sched changed
       RaiseEvent ScheduleChanged(Me, New EventArgs())
   End Sub
End Class

私有集合的替代方法是ScheduleCollection(of T). 对于活动的订阅者:

Public Class SomeOtherClass

    ' These need a reference to the Schedule object
    Private WithEvents Sched As Schedule
    ...
    Public Sub New(scObj As Schedule)
        Sched = scObj
    End Sub
End Class

SomeOtherClass现在将在 Left VS Dropdown abs 中有一个新条目,相关事件:

Private Sub Sched_ScheduleChanged(sender As Object,
                  e as EventArgs) Handles Sched.ScheduleChanged
     ' add code here to respond to schedule changes

End Sub

用法:

Dim foo = New SomeOtherClass(SchedObj)

无论创建什么对象,都会在构造函数中SomeOtherClass传递Schedule对象。如果它是由Schedule它创建的,它将是Me.

如果SomeOtherClass可以访问Schedule您可以放弃构造函数参数:

Public Sub New()
    Sched = mainSchedInstance
End Sub

在所有情况下,都Schedule需要存在,否则代码将尝试挂钩Nothing对象上的事件。

笔记

  • Sched在所有事件中传递对象 ( )似乎很奇怪Me(还有谁会发送ScheduleChanged事件?)。但是 VS 代码分析工具反对除Object sender, EventArgs e.
  • 如果您想在事件中传递信息,例如更改类型,请创建一个继承自的类EventsArgs并添加您想要的任何属性。其中之一可能是ScheduleItem添加的

还有其他方法可以实现这一点,例如它曾经Foo.Schedule并且SomeOtherClass需要了解事件。在这种情况下,Schedule 仍然生成事件,Foo订阅它,然后引发它自己的ScheduleChanged事件,传递事件参数。其他参与者订阅事件Foo。这被称为“冒泡”事件。


您还可以使用一种方法创建一个小类,只做一个事件。在这种情况下,它将由Schedule任何参与者通过非私有成员创建并可供任何参与者使用。 SomeOtherClass可以Schedule.ScheduleChangeNotifier从 Foo 中获得对 Foo 的引用。当列表更改时,Schedule调用触发事件的方法并且 Foo 不参与。

这种模式通常称为 EventBus,但可以将其视为 Broadcast-Receiver 设置:Schedule 使用该类广播通知,其他人使用它作为事件接收它们。当两个演员甚至不需要彼此了解时,它很有用。

一个例子是Foo.Bar需要知道一些事情Fizz.BlorgBar可以接收这些事件而不涉及FizzFoo超出将总线/通知器对象获取到Bar

它比冒泡事件少见,但有时非常有用。通常,如果这似乎是答案,我会尝试重新检查设计,看看是否可以简化事情。

于 2013-09-21T15:47:42.280 回答
0

List(Of )不提供开箱即用的功能。

您可以创建自己的实现IList(Of )并实现所需的事件,也可以使用现有的集合,如BindingList(Of )ObservableCollection(Of )

于 2013-09-21T06:51:48.713 回答