EventHandler aus einer .dll heraus erstellen.

  • VB.NET
  • .NET (FX) 4.0

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

    EventHandler aus einer .dll heraus erstellen.

    Hallo VB-Freaks,
    kann mir jemand sagen, wie man EventHandler aus einer Bibliothek heraus erstellt?

    Also wie man grundsätzlich einem per Code erzeugten Steuerelement einen EventHandler
    hinzufügt weiß ich, aber ich komme mit Folgendem nicht ganz klar (z.B.):

    VB.NET-Quellcode

    1. Public Shared Function Cells(ByRef PnlCells As Panel) As ArrayList
    2. Dim TmpList As New ArrayList
    3. Dim CellSz As Integer = 50
    4. Dim iCt As Integer = -1
    5. For Row As Integer = 1 To 402 Step CellSz - 1
    6. Row -= 2 * ((Row = 148) Or (Row = 297))
    7. For Col As Integer = 1 To 402 Step CellSz - 1
    8. Col -= 2 * ((Col = 148) Or (Col = 297))
    9. iCt += 1
    10. Dim Cell As New Label
    11. With Cell
    12. .Name = "Cell" & iCt.ToString
    13. .Location = New Point(Col, Row)
    14. .Size = New Size(CellSz, CellSz)
    15. .Font = New Font("Times New Roman", 20)
    16. .TextAlign = ContentAlignment.MiddleCenter
    17. .Text = iCt.ToString
    18. ' AddHandler Cell.Click, AddressOf Cell_Click
    19. End With
    20. PnlCells.Controls.Add(Cell)
    21. TmpList.Add(Cell)
    22. Next
    23. Next
    24. Return TmpList
    25. End Function

    Erläuterungen:
    Bei 1 übergebe ich der Funktion (in einer .dll !) ein Panel, auf das gezeichnet werden soll.
    Bei 2 erzeuge ich eine ArrayList, in der ich die zu erzeugenden Label-Referenzen speichern will.
    Ab 5. und 7. zeichne ich ein 9x9 großes Label-Feld auf das übergebene Panel.
    Bei 10 werden die Labels erzeugt und ihnen
    im Folgenden (11-19) ein paar Eigenschaften zugewiesen.
    Bei 20 werden jeweils die Labels dem Panel(-Container) und
    bei 21 die Referenzen der ArrayList (die bei 24 dem aufrufenden Form zur Verfügung steht)
    übergeben.

    Soweit so gut, aber der Haken liegt für mich in der bei 18 auskommentierten Zeile:

    Würde ich nun diese Funktion in einem Form direkt eingeben, dann tritt solange die
    Fehlermeldung "Cell_Click wurde nicht deklariert" auf, wie keine (Event-)Funktion
    mit dem Namen 'Cell_Click' vorliegt - also fügt man sie ein und alles ist in Ordnung!

    In meinem Fall, dass sich die Funktion in einer .dll befinden soll, weiß sie ja nichts
    von einer 'Cell_Click'-Funktion in dem Form!?
    Wie kann man das regeln? Weiß jemand hiefür eine Lösung?

    PS: Ich habe meine Frage etwas ausführlicher formuliert, da ich auf
    Missverständnisse basierende Antworten vermeiden möchte.
    mfG DHB

    Ich meine:
    :P Es sollten nur ernstzunehmende Beiträge eingestellt werden!
    :( Beiträge, die nur deren Anzahl in die Höhe treiben sollen, stehlen Lesern deren Zeit und schenken nur Frust.
    ;) Wenn ein Autor sein Thema für erledigt hält, sollte er dies kurz als letzten Eintrag vermerken.
    8) Leser wüssten dann, dass hier weitere Beiträge nicht mehr sinnvoll sind.
    @DHB Klar, so geht das nicht.
    1. Vergiss ArrayList, nimm List(Of Label), die ist typisiert.
    2. Gib der DLL Option Strict On.
    3. Gib dieser DLL-Prozedur ein Delegate als Parameter mit und weise dieses bei AddHandler zu:

      VB.NET-Quellcode

      1. Public Shared Function Cells(ByRef PnlCells As Panel, fct As [Delegate]) As List(Of Label)
      2. ' ...
      3. AddHandler Cell.Click, CType(fct, Global.System.EventHandler)
      4. ' ...
      5. End Function
      (Außer der Syntax nicht getestet).
    4. Teste dies zunächst in der aufrufenden Form.

    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!
    Hey RodFromGermany, danke zunächst für Deine Antwort.

    Ich bin nicht so fit mit dem Thema Delegates und wollte mich zunächst mal etwas umfangreicher über Delegates informieren, da meine Kenntnisse nur im Sinne von
    openbook.rheinwerk-verlag.de/e…cbaebbc950242178ce18ab6e6
    reichen. Dabei habe ich aber auch nichts Weiteres gefunden, das auf mein spezielles Problem anwendbar wäre.

    Was Du gepostet hast, habe ich umgesetzt und eine Fehlermeldung taucht in der .dll auch nicht mehr auf - da funktioniert´s. Wie ich allerdings in dem AnwendungsForm diese Pocedure aufrufe und dann später auf die ClickEvents für die Labels zugreifen kann, kriege ich auch nach längerem Probieren nicht hin, hierfür scheint mein Wissen über Delegates nicht zu reichen.

    Sollte ich es nicht hinbekommen, wird mir wohl nichts anderes übrig bleiben, als diese Funktion in das AnwendungsForm zu legen. Die andere Lösung (in einer .dll) wäre mir lieber (eleganter) und ich hätte das Delegatenthema natürlich auch gerne verstanden!
    mfG DHB

    Ich meine:
    :P Es sollten nur ernstzunehmende Beiträge eingestellt werden!
    :( Beiträge, die nur deren Anzahl in die Höhe treiben sollen, stehlen Lesern deren Zeit und schenken nur Frust.
    ;) Wenn ein Autor sein Thema für erledigt hält, sollte er dies kurz als letzten Eintrag vermerken.
    8) Leser wüssten dann, dass hier weitere Beiträge nicht mehr sinnvoll sind.
    @DHB

    Ich würde auch ein ListOf nehmen. Der Vorteil liegt darin, dass ListOf referenzen zu den erstellten Labels macht, und es ist auch ausgereifeter für den profesionellen Einsatz.

    Mit dem Code den du zeigst, können nur Vermutungen aufgestellt werden.
    Ich hab dir was in den Anhang gesetzt. Es ist nicht profihaft gemacht, und soll nur zeigen wie das Ganze umgesetzt werden kann.

    Beide Varianten funktionieren.

    EDIT: Bitte ändere so. Danke

    VB.NET-Quellcode

    1. Public Sub Label_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    2. If TypeOf DirectCast(sender, Label) Is Label Then
    3. Dim name As String = DirectCast(sender, Label).Name
    4. Stop
    5. End If
    6. End Sub
    7. 'zu
    8. Public Sub Label_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    9. If TypeOf sender Is Label Then '<<<<<<<<<<<<<<<<< HIER
    10. Dim name As String = DirectCast(sender, Label).Name
    11. Stop
    12. End If
    13. End Sub



    Freundliche Grüsse

    exc-jdbi
    Dateien
    • LabelEvent.zip

      (21,2 kB, 99 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „exc-jdbi“ ()

    DHB schrieb:

    Würde ich nun diese Funktion in einem Form direkt eingeben, dann tritt solange die
    Fehlermeldung "Cell_Click wurde nicht deklariert" auf, wie keine (Event-)Funktion
    mit dem Namen 'Cell_Click' vorliegt - also fügt man sie ein und alles ist in Ordnung!
    Das ist auch die typische Vorgehensweise.

    DHB schrieb:

    In meinem Fall, dass sich die Funktion in einer .dll befinden soll, weiß sie ja nichts
    von einer 'Cell_Click'-Funktion in dem Form!?
    Warum willst du die Ereignisbehandlung denn bitte in der DLL haben? Das ist doch total wiedersinnig? Du willst doch in einem

    DHB schrieb:

    . Wie ich allerdings in dem AnwendungsForm diese Pocedure aufrufe
    Was du machen willst, läuft im Endeffekt nur darauf hinaus, dass du die Methode Cell_Click selber aufrufen kannst.

    Was du machen kannst, ist entweder in dem Projekt, in welchem du deine Klasse Panel definierst, eine Methode Cell_Click zu implementieren ODER du legst diese in deiner Hauptanwendung fest.
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    weiß sie ja nichts von einer 'Cell_Click'-Funktion in dem Form!?

    Normal sollte die .dll auch nichts von dem Panel wissen. Bessere Herangehensweisen wurden ja bereits erwähnt. Wenn du allerdings daran festhalten willst, kannst du auch direkt einen EventHandler übergeben.

    Spoiler anzeigen

    C#-Quellcode

    1. private void Form1_Load(object sender, EventArgs e)
    2. {
    3. using (ExampleClass ec = new ExampleClass())
    4. ec.AddButtonToForm(this, ButtonClick);
    5. }
    6. private void ButtonClick(object sender, EventArgs e)
    7. {
    8. MessageBox.Show("Thank´s");
    9. }


    C#-Quellcode: Klasse (ExampleClass) repräsentiert die .dll

    1. public bool AddButtonToForm(Form frm, EventHandler clickEventHandler)
    2. {
    3. Button btn = new Button();
    4. btn.Location = new Point(((frm.ClientRectangle.Width - btn.Size.Width) - 10), (frm.ClientRectangle.Height - btn.Height) - 10);
    5. btn.Text = "Click Me";
    6. btn.Click += clickEventHandler;
    7. frm.Controls.Add(btn);
    8. return true;
    9. }

    Die ganze Form in die Dll überführen, bedeutet auch alle Komponenten und Steuerelemente zu kennen.

    Machbar wäre es schon. Man könnte sich rekursiv durch alle Controls tasten, und alle in eine ListOfT festhalten (oder das nur gewünsche Control so raussuchen). Erst dann ist es möglich Steuerelemente etc. in ein z.B. Panel zu adden. Das ClickEvent könnte man so problemlos dann auch in die Hauptanwendung nehmen.

    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    Hallo an Alle die mir helfen wollten,
    ich muss feststellen, dass mich Alle (bis vielleicht auf RodFromGermany) gründlich missverstanden haben.
    Ich will weder eine Form (@exc-jdbi) , noch ein Control (@Fakiz) oder ein Event (@Radinator) in der .dll haben, sondern:
    1. Ich habe lediglich der Function ein Panel ByRef zur Verfügung gestellt, auf dem die Labels gezeichnet werden sollen. Das Panel bleibt natürlich in dem aufrufenden Form; somit brauche ich auch nicht zusätzlich eine eigene PanelClass definieren (@Radinator) - es ist OK und funktioniert auch!
    2. Eine ArrayList - JETZT List(Of Label) - wird in der .dll zunächst temporär erzeugt, mit den Referenzen der Labels gefüllt und dem aufrufenden Form zur Verfügung gestellt; bleibt also auch nicht in der .dll - auch das funktioniert ebenfalls und brauch nicht weiter diskutiert werden!

    Aber nochmal, ich hoffe, ich kann´s jetzt deutlicher formulieren:
    Ich möchte innerhalb der .dll-Function nur ein Click-Event für die Labels definieren, das in der Anwendung dann, wie die Labels selbst, zur Verfügung steht.

    Ich denke, dass der Ansatz so sein muss, wie @RodFromGermany in dargestellt hat; komme aber damit nicht bis zum Ende durch - wie sieht der Zugriff auf die Click-Event-Procedure für die Labels in der Hauptanwendung aus?

    Übrigens: In meinem 2-ten Post schrieb ich bereits
    Was Du gepostet hast, habe ich umgesetzt...
    mfG DHB

    Ich meine:
    :P Es sollten nur ernstzunehmende Beiträge eingestellt werden!
    :( Beiträge, die nur deren Anzahl in die Höhe treiben sollen, stehlen Lesern deren Zeit und schenken nur Frust.
    ;) Wenn ein Autor sein Thema für erledigt hält, sollte er dies kurz als letzten Eintrag vermerken.
    8) Leser wüssten dann, dass hier weitere Beiträge nicht mehr sinnvoll sind.
    @DHB Es ist doch ein wenig anders. Mit Unterstützung von StackOverflow kommt dies raus, getestet.
    Die Prozedur Cells kannst Du nun in eine DLL packen:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Public handler As EventHandler
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. handler = New EventHandler(AddressOf Cell_Click)
    5. Cells(Panel1, handler)
    6. End Sub
    7. Public Shared Function Cells(ByRef PnlCells As Panel, handler As EventHandler) As List(Of Label)
    8. Dim TmpList As New List(Of Label)
    9. Dim CellSz As Integer = 50
    10. Dim iCt As Integer = -1
    11. For Row As Integer = 1 To 2
    12. For Col As Integer = 1 To 2
    13. iCt += 1
    14. Dim Cell As New Label
    15. With Cell
    16. .Name = "Cell" & iCt.ToString
    17. .Location = New Point(Col * 100, Row * 40)
    18. .Size = New Size(CellSz, CellSz)
    19. .Font = New Font("Times New Roman", 20)
    20. .TextAlign = ContentAlignment.MiddleCenter
    21. .Text = iCt.ToString
    22. AddHandler Cell.Click, handler
    23. End With
    24. PnlCells.Controls.Add(Cell)
    25. TmpList.Add(Cell)
    26. Next
    27. Next
    28. Return TmpList
    29. End Function
    30. Private Sub Cell_Click(sender As Object, e As EventArgs)
    31. Dim lbl = CType(sender, Label)
    32. lbl.ForeColor = Color.Red
    33. End Sub
    34. 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!
    Hallo RodFromGermany,
    tausend Dank für deine Hilfe :thumbsup: ; das war genau das, was ich gesucht habe!
    Darauf wäre ich nie gekommen, wenn man es aber nachvollzieht, ist es sowas von logisch...
    mfG DHB

    Ich meine:
    :P Es sollten nur ernstzunehmende Beiträge eingestellt werden!
    :( Beiträge, die nur deren Anzahl in die Höhe treiben sollen, stehlen Lesern deren Zeit und schenken nur Frust.
    ;) Wenn ein Autor sein Thema für erledigt hält, sollte er dies kurz als letzten Eintrag vermerken.
    8) Leser wüssten dann, dass hier weitere Beiträge nicht mehr sinnvoll sind.