3

Visual Basic.net では、イベント ハンドラーを T のリストに追加して、リストが変更されるたびにこのイベントが呼び出されるようにすることはできますか?

たとえば、Schedule というクラスがあり、この Schedule に ScheduleItem のリストがある場合、このリストが変更されるたびに呼び出されるイベントを追加するにはどうすればよいですか?

4

2 に答える 2

4

リストが変更されたときにイベントを発生させるコレクションがありますが ( BindingList(of T)1 つ)、イベントはリストが存在するクラス/フォームでのみ使用できます。より広範な実装のために、Scheduleクラスはイベントを発生させることができます。

  1. リストのみScheduleを変更するようにしてください。つまりList(Of T)、プライベート メンバーである必要があります。他のオブジェクトは、すべての変更を完全に認識して見逃さないように、それを介して変更を行う必要があります。

  2. 変更イベントとは何かを決定します。アイテムの追加と削除は明らかですが、ScheduleItem多分.StartTimeまたは同様のプロパティの内容によっては、イベントも同様です。(実際INotifyPropertyChangedにはアイテムクラスで必要になります)

  3. Add と Delete の場合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

プライベート コレクションに代わるものは、 の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

SomeOtherClassLeft VS Dropdown abs 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

使用法:

Dim foo = New SomeOtherClass(SchedObj)

オブジェクトを作成しているものは何でも、コンストラクターでSomeOtherClassオブジェクトを渡します。Scheduleによって作成されている場合は、ScheduleになりますMe

SomeOtherClassアクセスできる場合はSchedule、コンストラクター引数を省略できます。

Public Sub New()
    Sched = mainSchedInstance
End Sub

いずれの場合もSchedule存在する必要があります。存在しない場合、コードはオブジェクトのイベントにフックしようとしNothingます。

ノート

  • Schedすべてのイベントでオブジェクト ( )を渡すのは奇妙に思えるかもしれませんMe(他に誰がScheduleChangedイベントを送信するでしょうか?)。しかし、VS コード分析ツールは、.NET 以外のイベント シグネチャに反対しObject sender, EventArgs eます。
  • イベントでどのような変更が行われたかなどの情報を渡したい場合は、継承元のクラスを作成し、EventsArgs必要なプロパティを追加します。それらの1つはScheduleItem追加される可能性があります

Foo.Scheduleこれを実装する方法は他にもあります。たとえばSomeOtherClass、イベントについて知る必要がある場合などです。この場合でも、Schedule はイベントを生成し、Fooサブスクライブしてから、独自のScheduleChangedイベントを発生させ、イベント引数を渡します。他のアクターは のイベントにサブスクライブしFooます。これは、イベントの「バブルアップ」と呼ばれます。


また、イベントを発生させるだけで、メソッドが 1 つの小さなクラスを作成することもできます。この場合、それはSchedule非プライベート メンバーを介して任意のアクターによって作成され、利用可能になります。 from FooSomeOtherClassへの参照を取得できます。Schedule.ScheduleChangeNotifierリストが変更さScheduleれると、イベントを発生させるメソッドが呼び出され、Foo は関与しません。

通常、このパターンは EventBus と呼ばれますが、Broadcast-Receiver セットアップと考えることができます。Schedule はクラスを使用して通知をブロードキャストし、他のクラスはそれを使用してそれらをイベントとして受信します。2 つのアクターが互いのことを知る必要がない場合に便利です。

例としてFoo.Bar、 から何かを知る必要がある場合がありFizz.Blorgます。これらのイベントは、バス/通知オブジェクトを に取得することを必要とBarせずに受け取ることができFizzます。FooBar

イベントをバブリングするほど一般的ではありませんが、非常に役立つ場合があります。通常、それが答えだと思われる場合は、設計を再検討して、単純化できないかどうかを確認します。

于 2013-09-21T15:47:42.280 に答える
0

List(Of )これはそのままでは提供されません。

独自の実装を作成して必要なイベントを実装するか、またはIList(Of )のような既存のコレクションを使用することができます。BindingList(Of )ObservableCollection(Of )

于 2013-09-21T06:51:48.713 に答える