为列表添加事件处理程序

时间:2013-09-21 06:47:42

标签: .net vb.net list event-handling

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

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

2 个答案:

答案 0 :(得分:3)

有些集合会在列表更改时引发事件(BindingList(of T)为一个集合),但事件只对列表所在的类/表单可用。为了更广泛的实施,您的Schedule班级可以举起活动。

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

  2. 决定什么是变更事件。添加和删​​除项目是显而易见的,但取决于ScheduleItem中的内容.StartTime或类似属性也是事件。 (这实际上需要{item 1}上的INotifyPropertyChanged

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

  4. 谁将要消费(或获得)这些活动?形式?其他类结构?

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

    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
    

    私有集合的替代方法是Schedule继承Collection(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以外的事件签名。
    • 如果您想在事件中传递信息,例如 type 更改,请创建一个继承自EventsArgs的类,并添加您想要的任何属性。其中一个可能是ScheduleItem添加

    还有其他方法可以实现这一点,例如Foo.ScheduleSomeOtherClass需要了解该事件。在这种情况下,Schedule仍会生成事件,Foo订阅它,然后引发自己的ScheduleChanged事件,传递事件args。其他演员在Foo订阅了该活动。这被称为“冒泡”事件。


    您还可以使用一种方法创建一个小类,除了引发事件之外什么都不做。在这种情况下,它将由Schedule创建,并通过非私人成员可供任何参与者使用。 SomeOtherClass可以从Foo获得对Schedule.ScheduleChangeNotifier的引用。当列表发生变化时,Schedule会调用触发事件的方法,而不涉及Foo。

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

    一个例子是Foo.Bar需要了解来自Fizz.Blorg的内容:Bar可以接收这些事件而不会让FizzFoo无法获得公交/ notifier对象为Bar

    它不像鼓泡事件那么常见,但有时非常有用。通常,如果看起来似乎是答案,我会尝试重新检查设计,看看是否可以简化。

答案 1 :(得分:0)

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

您可以创建自己的IList(Of )实施并实施所需的活动,也可以使用BindingList(Of )ObservableCollection(Of )等现有收藏。