In Visual Basic.net, is it possible to add an event handler to a List of T such that whenever the list is changed, this event is called?
For example, if I have a Class called Schedule, and this Schedule has a List of ScheduleItem, how can I add an event that will be called whenever this List is changed?
There are collections which raise events when the list changes (BindingList(of T) for one) but the events are only going to be available to the class/form where the list lives. For a broader implementation your Schedule Class can raise events.
Make sure only Schedule makes changes to the list. That is, your List(Of T) should be a private member. Other objects should make changes thru it so that it is fully aware of all changes so that none are missed.
Decide what is a change event. Add and delete an item are obvious, but depending on what is in ScheduleItem maybe .StartTime or similar properties are events as well. (That would actually require INotifyPropertyChanged on the item class)
For just Add and Delete, every time Schedule adds or deletes an item from the internal List, it would raise the event to notify the subscribers.
Who is going to consume (or get) these events? Forms? Other class structs?
A simple way to do this, once all changes are happening in the class which 'owns' the list is a custom event:
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
An alternative to the private collection is for Schedule to inherit from something like Collection(of T). For the subscribers of the event:
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 will now have a new entry in the Left VS Dropdown abs a related event:
Private Sub Sched_ScheduleChanged(sender As Object,
e as EventArgs) Handles Sched.ScheduleChanged
' add code here to respond to schedule changes
End Sub
Usage:
Dim foo = New SomeOtherClass(SchedObj)
Whatever is creating the SomeOtherClass object passes the Schedule object in the constructor. If it is being created by Schedule it would be Me.
If SomeOtherClass has access to Schedule you can forego the constructor argument:
Public Sub New()
Sched = mainSchedInstance
End Sub
In all cases, Schedule needs to exist or the code will be trying to hook to events on a Nothing object.
Notes
Sched object (Me) in all the events
(who else would send ScheduleChanged events?). But the VS code analysis tools object to an event signature other than Object sender, EventArgs e.EventsArgs and add whatever properties you want. One of those could be the ScheduleItem addedThere are other ways to implement this, for instance of it was Foo.Schedule and SomeOtherClass needs to know about the event. In this case, Schedule still generates the event, Foo subscribes to it and then raises its own ScheduleChanged event, passing along the event args. Other actors subscribe to the event on Foo. This is referred to as 'bubbling up' an event.
You can also create a small class with one method and does nothing more than raise an event. In this case, it would be created by Schedule and be available to any actor via a non private member. SomeOtherClass could get a reference to the Schedule.ScheduleChangeNotifier from Foo. When the list changes, Schedule calls the method which fires the event and Foo isn't involved.
This pattern is usually called an EventBus, but it can be thought of as a Broadcast-Receiver setup: Schedule uses the class to broadcast a notice, others use it to receive them as an event. It is useful when there is otherwise no need for the 2 actors to even know about each other.
An example would be Foo.Bar needing to know about something from Fizz.Blorg: Bar could receive those events without involving Fizz or Foo beyond getting the bus/notifier object to Bar.
It is less common than bubbling up events but sometimes very useful. Usually though if it seems that is the answer, I try to re-examine the design to see if things could be simplified.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With