RaiseEvent innerhalb einer Klassenbibilothek funktioniert nicht

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

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    RaiseEvent innerhalb einer Klassenbibilothek funktioniert nicht

    Hallo,

    ich habe eine Klassenbibliothek erstellt die die Klassen A und B enthält

    A ist ein Control mit verschiedenen ComboBoxen.
    B ist ein Control mit verschiedenen Buttons.

    In A sind zusätzlich mehrere Instanzen von B integriert, damit sich Änderungen des Entwicklers an B direkt auf alle Instanzen davon in A auswirken.

    Das funktioniert auch alles soweit.

    Mein Problem ist nun: drücke ich in einer Instanz von B in A einen bestimmten Button, soll B das an A mitteilen und A darauf entsprechend reagieren.

    Das nachfolgende funktioniert nicht.

    VB.NET-Quellcode

    1. Public Class Class_B
    2. Public Event MeinEreignis()
    3. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    4. RaiseEvent MeinEreignis
    5. End Sub
    6. End Class
    7. Public Class Class_A
    8. WithEvents Ereignis As New Class_B
    9. Private Sub _Ereignis() Handles Ereignis.MeinEreignis
    10. MsgBox("Test")
    11. End Sub
    12. End Class


    Und einen Handler einrichten mit

    VB.NET-Quellcode

    1. Public Class Class_A
    2. AddHandler Class_a.MeinEreignis, AddressOf test
    3. Private Sub test()
    4. MsgBox("Test")
    5. End Sub
    6. End Class


    wird immer mit „Der Verweis auf einen nicht freigegebenen Member erfordert einen Objektverweis.“ quittiert.
    Lassen sich innerhalb von Klassenbibilotheken keine Events handhaben?
    Ich habe versucht, es mit UserControls nachzubauen. Klappt problemlos.
    Das einzige, was mir noch gemeldet wurde, ist Zeile#9:

    Benenne _Ereignis um und probiere nochmal - falls das überhaupt der Arbeitscode ist.
    Dass Dein 2. Versuch nicht klappt, liegt daran, dass es ja auch möglich sein kann, dass man für Class_A-Objekt 1 einen anderen Handler andocken will als für Class_A-Objekt 2. Daher muss man mit Instanzen arbeiten und kann nicht das Klassenereignis an sich einem EventHandler zuordnen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @roepke Try this:

    VB.NET-Quellcode

    1. Public Class Form1
    2. WithEvents Ereignis As New Class_A
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. Ereignis.Ereignis()
    5. End Sub
    6. Private Sub EreignisHandler() Handles Ereignis.MeinEreignis
    7. MessageBox.Show("Ereignis")
    8. End Sub
    9. End Class
    10. Public Class Class_A
    11. Public Event MeinEreignis()
    12. Public Sub Ereignis()
    13. RaiseEvent MeinEreignis()
    14. End Sub
    15. End Class
    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!
    noch die kleinkarierte Empfehlung, die Benamsung zu überdenken.
    Imo sollte weder ein Objekt noch eine Methode jemals "Ereignis" heissen.
    Solch ist schwer lesbar und kann nur zu Irritationen führen.

    Ein Ereignis ist ein Ereignis.
    Ein Objekt ist kein Ereignis, sondern ist Instanz einer Klasse.
    Eine Methode ist auch kein Ereignis, sondern löst ggfs. ein Ereignis aus - oder behandelt eines.
    Hallo zusammen,

    erst mal danke für die Antworten.

    @VaporiZed: Es handelt sich hier nur um Beispielcode zur Verdeutlichung meines Problems. Sorry wenn sich ein Fehler eingeschlichen hat. Als UserControl oder Windows Forms-Anwendung funktioniert das Ganze auch bei mir. Das Problem ist, dass es als Anwendungstyp „Klassenbibliothek“ nicht funktioniert. Ich bekomme aber auch keine Fehlermeldung. Das Ereignis in Class_B wird in Class_A einfach nicht erkannt.

    @RodFromGermany: Vielen Dank. Dein Beispiel funktioniert, nur ist mein Button der das Ereignis triggern soll in Class_B und Class_A soll darauf reagieren. Habe zur Verdeutlichung nochmal ein Bild angehängt.

    @Erfinder des Rades: Danke für die Kleinkariertheit. Wie vorher schon geschrieben handelt es sich hier um einen Beispielcode um mein Problem darzustellen. In meinem wirklichen Code habe ich auf sinnvolle und vor allem richtige Bezeichnungen geachtet.

    Mein Verdacht bei genauerem anschauen ist folgender:

    In einer Windows Form Anwendung sind die einzelnen Klassen nicht ineinander verkapselt, wie es hier mit Class_B in Class_A der Fall ist. Daher ist es wohl möglich Ereignisse zwischen Klassen auszulösen.
    Da Class-B aber in Class_A gekapselt ist, also quasi Class_A das „Hauptprogramm“ stellt, ist wohl der Zugriff von Class_B auf Class_A so nicht möglich.
    Anders herum kann aber Class_A sehr wohl auf Elemente von Class_B zugreifen.
    Überlegung: Evtl. könnte es funktionieren, wenn nun Class_B das Ereignis feuert und global in einem Modul eine Sub anstößt, die dann das Ereignis wieder an die Klassen verteilt.

    LG
    Bilder
    • Event.jpg

      29,55 kB, 683×417, 135 mal angesehen

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

    Nee, das geht schon. Ich habe aufgrund Deiner hiesigen Info folgendes gemacht:
    • Steuerelementbibliothek erstellt -> UserControl entsteht (UC1)
    • 2. UserControl hinzugefügt (UC2)
    • im 1. zusätzlich zu Deinem Code noch per Button ne Sub, die den UC1-Controls ne neue UC2-Instanz hinzufügt
    • kompilieren und in nem WinForms-Projekt einbinden
    • eine neue UC1-Instanz dem Form per Button_Click hinzufügen
    • auf den UC1-Instanz-Button geklickt, damit ne UC2-Instanz entsteht
    • auf den UC2-Button geklickt -> MessageBox kommt, weil UC1 auf das UC2-Event reagiert
    Wären Events nicht möglich, würden ja auch die Button-EventHandler nicht funktionieren.
    Mir ist klar, dass Du bereits geschrieben hast, dass Du es erfolgreicht mit UCs probiert hast. Aber vielleicht sagst Du uns, was die DLL für eine Projekttyp ist und Class A und B für Klassentypen sind, vielleicht kommen wir so weiter.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    roepke schrieb:

    nur ist mein Button der das Ereignis triggern soll in Class_B und Class_A soll darauf reagieren
    Ja und?
    Dann verstehe das Beispiel und setze es entsprechend um.
    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!

    roepke schrieb:

    Wie vorher schon geschrieben handelt es sich hier um einen Beispielcode um mein Problem darzustellen. In meinem wirklichen Code habe ich auf sinnvolle und vor allem richtige Bezeichnungen geachtet.

    Diese Vorgehensweise ist absolut kontraproduktiv, kommt hier aber immer wieder vor.
    Das führt ständig zu Missverständnissen und überflüssigen Bemühungen der Helfer.
    Es ist doch absolut logisch, daß man genau den code postet, der probleme bereitet, Ausnamen stellen rein konzeptionelle Fragen da !
    Hallo zusammen,

    so langsam gebe ich auf.
    Ich dreh mich seit Tagen im Kreis. Hab jetzt wirklich alle Register gezogen die ich (nach meinem Wissensstand) ziehen kann. Habe (fast) das gesamte Internet durchgelesen und alles probiert was mir eingefallen ist. Es funzt einfach nicht!

    Ich hasse es, wenn Threads in Foren mitten in der Lösungssuche abbrechen oder mit „Jetzt geht’s“ beendet werden. Daher melde ich mich nochmal und krieche zu Kreuze.

    Ich bin wieder ganz am Anfang. Habe alles aus meinem Testprojekt rausgelöscht. Habe nur die simple Struktur mit dem Public Event und WithEvents drinnen gelassen. Und das Testprojekt mal angehängt.

    VB ist scheinbar einfach nicht meine Welt. Ich kann C und VHDL, darin bin ich wirklich fit, aber VB überfordert mich an dieser Stelle. Ich konnte das Ganze über globale Variablen zum Laufen bringen, aber das ist weder elegant noch kann es die Lösung sein.

    Also entweder sagt ihr mir nun: geh putzen! Vielleicht kannste das oder es nimmt sich jemand meines Beispielprojekts an und tippt die entscheidende Info da rein, damit es das tut was es tun soll und ich kann noch echt was dazu lernen.

    LG
    Dateien
    Das Problem ist, dass Du ein Event von einem anderen Control erwartest als tatsächlich auftaucht. Du hoffst auf das Event des Objekts ButtonClickedOnChildControl, wenn Parent und Child angezeigt werden. Das Problem dabei: Was Du als Child siehst, nennt sich ChildForm1. Dies ist in der ParentForm.Designer.VB ganz unten deklariert. Dieses feuert Events, wenn man auf den Button klickt. ButtonClickedOnChildControl hingegen ist zwar ein existentes Objekt. Aber es wird nirgends angezeigt. Daher kann man es auch nicht anklicken und es kommen keine Events an. Das liegt daran, dass Du zu den ParentForm.Controls diese Objektinstanz nicht hinzugefügt hast. Wenn Du das per ParentForm.Controls.Add(ButtonClickedOnChildControl) gemacht hättest, würdest Du 2 ChildForms sehen. Beide erzeugen dann das eigens kreierte Event.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Sowas hab ich mir ja fast schon gedacht. Objekte und Instanzen davon... Der Tipp hat mir gefehlt. Ich dreh mich seit Tagen im Kreis und seh vor lauter Bäumen den Wald nicht.

    VB.NET-Quellcode

    1. Public Class ParentControl
    2. 'WithEvents ButtonClickedOnChildControl As New ChildControl
    3. Private Sub ChildForm_OnChanged(sender As Object, e As EventArgs) Handles ChildForm1.EventButtonClickedOnChildControl
    4. MsgBox("ButtonClickedOnChildControl")
    5. End Sub
    6. End Class


    Das tut jetzt was es soll.
    Damit Du schreiben kannst ... Handles ChildForm1.EventButtonClickedOnChildControl. Ohne WithEvents gäbe es nen Compilerfehler. Dann müsstest Du mit AddHandler ChildForm1.EventButtonClickedOnChildControl, AddressOf DieVerarbeitungssub arbeiten, um das Event mit einem EventHandler Deiner Wahl zu verdrahten.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    roepke schrieb:

    WithEvents
    ist Geschmackssache.
    Mit funktioniert es wie im Designer und Du musst die Variable in die Klasse packen.
    Ohne kann eine lokale Instanziierung in einer Prozedur ausreichen (muss nicht!).
    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!