Ereignisprozedur mit mehreren Sendern - Teil 2

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    Ereignisprozedur mit mehreren Sendern - Teil 2

    Hi,

    Ich habe eine EventRoutine, die von zwei Ereignissen ausgelöst wird. Jetzt möchte ich wissen, wer "gefeuert" hat.

    ich hatte vor einiger Zeit schon mal einen ähnlichen Post eingestellt und auch eine sehr hübsche Lösung erhalten. Die habe ich jetzt versucht auf diese Situation zu übertragen. Leider klappt das nicht:

    VB.NET-Quellcode

    1. Private Sub dgvEdit_CellClickEnter(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEdit.CellClick,
    2. dgvEdit.CellEnter
    3. Debug.Print("dgvEdit CellClick or CellEnterEvent")
    4. If sender Is dgvEdit.CellClick Then ...


    Klar, die Syntax ist nicht korrekt, denn dgvEdit.CellClick ist ein EVENT ... und da kriege ich von Intellisense sofort die Meldung, dass ich RaiseEvent verwenden soll ... aber das ist natürlich nicht das, was ich haben will.

    Wie kann ich denn abfragen, welches Event gefeuert hat ? Das sollte doch relativ leicht zu machen sein ...

    LG
    Peter
    Das ist so einfach nicht moeglich, schliesslich haben wir kein EventLog zur verfuegung.

    Du koenntest dir eine abgeleitete DataGridView ertellen, wo beide Events einzeln gehandelt werden, in den Subs der Events kannst du 1 eigenes Event Raisen, welche die noetigen Infos dann mitschickt.
    And i think to myself... what a wonderfuL World!
    Ok, dann geht das nicht ! Du hast ja schon angeregt, das Problem einfach zu umgehen. Die naheliegenste Lösung ist wohl: separate Event Routinen, die eine gemeinsame Sub aufrufen. Damit kann ich auch leben ...

    Dein Rat hilft mir trotzdem weiter ... denn jetzt kann ich meine Suche in dieser Hinsicht einstellen. Das ist ja auch etwas wert. :)

    Vielen Dank und liebe Grüße
    Peter
    Eigendlich finde ich das wenig sinnvoll, aber so koennte das aussehen, so sind die Events dann "gebuendelt".

    VB.NET-Quellcode

    1. Public Class MyExtendedDataGridView
    2. Inherits DataGridView
    3. Public Event MyCellEvent(ByVal sender As Object, ByVal e As MyExtendedDataGridViewCellEventArgs)
    4. Private Sub MyExtendedDataGridView_CellClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles Me.CellClick
    5. RaiseEvent MyCellEvent(Me, New MyExtendedDataGridViewCellEventArgs With {.ColumnIndex = e.ColumnIndex, .RowIndex = e.RowIndex, .Event = MyCellEvents.CellClick})
    6. End Sub
    7. Private Sub MyExtendedDataGridView_CellEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles Me.CellEnter
    8. RaiseEvent MyCellEvent(Me, New MyExtendedDataGridViewCellEventArgs With {.ColumnIndex = e.ColumnIndex, .RowIndex = e.RowIndex, .Event = MyCellEvents.CellEnter})
    9. End Sub
    10. End Class
    11. Public Class MyExtendedDataGridViewCellEventArgs
    12. Public ColumnIndex As Integer
    13. Public RowIndex As Integer
    14. Public [Event] As MyCellEvents
    15. End Class
    16. Public Enum MyCellEvents
    17. CellClick
    18. CellEnter
    19. End Enum
    And i think to myself... what a wonderfuL World!
    Wollte nur noch einschmeißen es ist sogar Möglich, man könnte über den StackTrace gehen. Aber Sinnvoll ist es auf diese Art auf jeden Fall nicht :D
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    Peter329 schrieb:

    Private Sub dgvEdit_CellClickEnter(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEdit.CellClick, dgvEdit.CellEnter

    Das funktioniert hier nur deshalb, weil ZUFÄLLIG die Signaturen des Eventhandlers gleich sind.
    Der sender in dieser Nomenklatur ist IMMER das Objekt, das dieses Event ausgelöst hat (i.e. ein Control).
    Die Unterscheidung erfolgt über die Abonnierung des Events. Wenn Du's von Hand machst, siehts ja so aus, und wird wohl klar:

    VB.NET-Quellcode

    1. Addhandler dgvedit.CellClick, AddressOf CellClickRoutine
    2. Addhandler dgvedit.CellEnter, AddressOf CellEnterRoutine

    Die Unterscheidung des auslösenden Events ist so dann natürlich aus der Routine heraus nicht möglich.
    ok, das verstehe ich schon, dass die Signaturen der Events gleich sein müssen. Und in diesem Fall sind die Signaturen ja nicht unbedingt völlig zufällig identisch.

    Ich verstehe auch, dass die EventArguments e. nützlich sind, um gewisse Eigenschaften auszuwerten. Und dass die Struktur dieses Parameters natürlich von der Art des Events abhängt.

    Was ich aber nicht verstehe, das ist der Parameter

    VB.NET-Quellcode

    1. sender as Object


    Ein Object ist ja nun ein sehr allgemeines Konstrukt ... und natürlich muss man das erst mal in den Griff bekommen.

    VB.NET-Quellcode

    1. Private Sub myFields_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged,
    2. TextBox2.TextChanged
    3. If sender Is TextBox1 Then
    4. ' was tun
    5. Else If sender Is TextBox2 Then
    6. ' wieder was tun
    7. End If


    So kann man herausfinden, welche TextBox gefeuert hat. Also offensichtlich ist sender ein Pointer, der auf ein Object zeigt, das irgendwo abgespeichert ist.

    Und bei CellEnter und CellClick kann man diesen Pointer jetzt nicht mehr auswerten ?

    Also irgendwie verstehe ich dann nicht, warum und wozu man den Parameter sender in diesem Fall dann überhaupt braucht.

    Ich hoffe, jemand kann mir freundlich ein wenig Nachhilfeunterricht geben ... :)

    LG
    Peter

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Peter329“ ()

    Doch, Doch.
    Wenn Du das Event feuerst, sieht das so aus:

    VB.NET-Quellcode

    1. Public Class MyClass
    2. Public Event MyEvent(sender as Object, e as MyEventArgs)
    3. .
    4. .
    5. .
    6. Public Sub HierTutSichWas
    7. RaiseEvent MyEvent(me, New EventArgs)
    8. End Sub
    9. .
    10. .
    11. .
    12. End Class


    In der empfangende Klasse dann so

    VB.NET-Quellcode

    1. Public ReceivingClass
    2. Private _MyClass as MyClass
    3. Public Sub WasAuchImmer
    4. _MyClass=New MyClass
    5. Addhandler _MyClass.MyEvent, Addressof MyEventHandler
    6. End Sub
    7. Private Sub MyClass_MyEvent(sender as Object, e as MyEventArgs)
    8. .
    9. .
    10. .
    11. End Sub
    12. End Class

    Wenn Du nun ein zweites Event aif den gleichen Handler abonnierts

    VB.NET-Quellcode

    1. Addhandler _MyOtherClass.MyOtherEvent, Addressof MyEventHandler

    dann müssen natürlich die Signaturen übereinstimmen. Und innerhalb des Eventhandlers kannst Du Deinen sendenden Typ dan wie folgt zrückgewinnen:

    VB.NET-Quellcode

    1. Private Sub MyClass_MyEvent(sender as Object, e as MyEventArgs)
    2. Select Case True
    3. Case sender Is MyClass
    4. ' Mach dit
    5. Dim _MyClass = DirectCast(sender, MyClass)
    6. Case sender is MyOtherClass
    7. ' Mach dat
    8. Dim _MyOtherClass = DirectCast(sender, MyOtherClass)
    9. Case Else
    10. ' Da ist was schiefgelaufen, da hat irgendwer das Event ebenfalls abonniert.
    11. End Select
    12. End Sub

    Du kannst also sehr wohl das sendende Objekt in eine bekannte Form Casten. Und da die Signatur der abonnierten Events übereinstimmt, liegen Dir über die Eventargs immer die gleichen Informationen vor.
    Das tatsächlich auslösende Event kannst Du nur dann ermitteln, wenn diese Information in den EventArgs mitgegeben ist.

    us4711 schrieb:

    VB.NET-Quellcode

    1. RaiseEvent MyEvent(me, New EventArgs)
    Dafür gibt es bei .NET eine statische Variable:

    VB.NET-Quellcode

    1. RaiseEvent MyEvent(me, EventArgs.Empty)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hi
    außerdem sollte man statt

    VB.NET-Quellcode

    1. Public Event MyEvent(sender as Object, e as MyEventArgs)

    auf EventHandler(Of T) zurückgreifen:

    VB.NET-Quellcode

    1. Public Event MyEvent As EventHandler(Of MyEventArgs)

    Andernfalls wird vom Compiler ein überflüssiger zusätzlicher Delegat erzeugt, der dem EventHandler entspricht. Außerdem ist dann das Erben von EventArgs für MyEventArgs verpflichtend.

    Der Fehler mit dem New EventArgs liegt darin, dass es New MyEventArgs lauten müsste.

    Viele Grüße
    ~blaze~

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „~blaze~“ ()