Wie bei Laufzeit Button richtig click event setzen

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

Es gibt 34 Antworten in diesem Thema. Der letzte Beitrag () ist von Waxweazle.

    @RodFromGermany: Nein möchte nicht mit dem DGV arbeiten, hatte ich hier erklärt warum. Wie bei Laufzeit Button richtig click event setzen

    @VaporiZed: Mit dem DGV wäre ich nicht zufrieden siehe oben. Usercontroll hatte ich mal mal am Anfang angeschaut und gedacht wäre für meinen Fall nicht das richtige. Habe noch nicht mit Usercontroll gearbeitet, muss man aber dabei auch sagen. Deswegen auch keine Plan wie das vonstatten gehen könnte. Aber das was du in den Bildern andeutest, sieht nach einem Weg für mein Problem aus.
    Denke das mit dem dynamischen erstellen meiner Buttons war mal keine gute Idee von mir. Scheint mal keine gute Lösung zu sein, das habe ich mittlerweile verstanden.
    Ok, damit könnte jetzt erstmal die Richtung feststehen, in die wir uns bewegen. Weg vom DGV, hin zum UCE.
    Das Vorgehen ist einfach. Du fügst als neues Projektelement ein "Benutzersteuerelement" hinzu, versiehst es mit den 2 TextBoxen und Deinen 3 Buttons und erstmal gut. Im Hauptformular erfolgt das dann so, wie mrMo schon u.a. andeutete: FlowLayoutPanel aus den Container-CEs auf Dein Hauptformular ziehen. Und wenn Du dann eine "Kundenbox" dazupacken willst:

    VB.NET-Quellcode

    1. Dim KundenPanel As New UserControl1
    2. FlowLayoutPanel1.Controls.Add(KundenPanel)

    Die CEs sollten sinnvollere Namen als UserControl1 und FlowLayoutPanel1 bekommen, aber das dürfte klar sein. Probier mal aus, ob Du das soweit hinbekommst und mit dem Ergebnis zufrieden bist.
    Da das User-CE eine eigene Klasse ist, kannst Du diesem natürlich auch eigene Variablen etc. verpassen. Passend dazu wiederhole ich meine Frage, ob Du zu diesem Zeitpunkt (User-CE+FL-Panel erfolgreich implementiert) schon Ideen hast, wie Du die DataTable-Zeile mit dem User-CE verknüpfen kannst, damit dann die Buttons wissen, mit welchen Daten sie später genau arbeiten sollen. Es gibt mehrere Möglichkeiten. Auch fielen vielen Lesern bestimmt einige ein. Aber es geht ja darum, dass Du selber Idden einbringst, um für zukünftige Probleme gewappnet zu sein.
    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.

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

    Jo - so Extrawünsche kosten eben enormen Aufwand - und reichen doch nicht an die Leistungsfähigkeit der Standard-Lösung (DGV) heran.

    Du wirst Databinding neu erfinden müssen, also Synchronisierung von Anzeige (und auch Selektion!) mit der BindingSource - das wird noch das einfachste sein.
    Also die DGV-Features nachprogrammieren - besser nicht versuchen, Rad neu zu erfinden.
    Vielleicht leitest du von FlowlayoutPanel ab, und übergibst ihm databindable UserControl-Typen - quasi als "Datatemplate" - und das "ItemsControl" - so nenne ich das abgelittene Flowlayoutpanel jetzt - kümmert sich um die Synchronisiererei mitte BindingSource.
    Diese Vorschläge sind jetzt bestimmten Wpf-Konzepten nachempfunden - Wpf unterstützt so Gui-SchnickSchnack-Wünsche viel besser als WinForms - und wirklich durchdacht.

    ( Und dann kannste immer noch nicht, auf einen SpaltenHeader klicksen, und sortiert ist. :P )
    ( Und ab so ca. 300 Datensätzen wird das vmtl. abka... wg. immensen Resourcenverbrauch :P )
    @VaporiZed: Danke mal für deine Idee. Verständnisfrage, da ja die Anzahl der FlowLayoutPanel variabel ist (möchte ja später auswählen wie viele angezeigt werden sollen) muss ich dann sagen wir mal 10 Stück einbauen und diese dann sichtbar/unsichtbar machen oder kann ich die in der Laufzeit erstellen. Arbeite zum ersten mal mit FlowLayoutPanel und usercontrol.

    Passend dazu wiederhole ich meine Frage, ob Du zu diesem Zeitpunkt (User-CE+FL-Panel erfolgreich implementiert) schon Ideen hast, wie Du die DataTable-Zeile mit dem User-CE verknüpfen kannst, damit dann die Buttons wissen, mit welchen Daten sie später genau arbeiten sollen.

    Nein noch nicht genau, denke erstmal das mit dem oben genante abarbeiten und dann kommt mir dabei hoffentlich eine Idee, weil erstmal das FlowLayoutPanel und usercontrol auf die Kette bekommen.
    Wie in Post#22 per Code angegeben: Sobald Du die gewünschten Kunden und deren Reihenfolge hast, die Du in Deinem FLP haben willst, nutzt Du FLP.Controls.Add(UC), um 1 neues User-CE dem FLP hinzuzufügen. Und das machst zu eben x-mal, wenn Du x Kunden angezeigt bekommen haben willst. Da brauchst Du nix auf unsichtbar zu schalten, da die User-CEs quasi frisch auf Bedarf erstellt und zum FLP hinzugefügt werden. Wieviele Kunden sollen denn minimal/maximal angezeigt werden? Wenn das zwsichen 0 und 10 sein sollen, abhängig davon, was der Benutzer haben will, dann macht sich das mit dem Controls.Add am besten.
    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.
    @VaporiZed: Ja werden wohl nicht mehr als zehn, könnte das ja auch auf zehn begrenzen. Sollen ja nur die wichtigsten werden, die "Nebenkunden" frühstücke ich anders ab.
    Ah Ok, also werden diese "dynamisch" erstellt wie ich es mit meiner ersten Idee gemacht habe nur mit controls und FLP. Ok das hilft mir weiter. Also erstelle ich meine controls alle in einem FLP mit FLP.Controls.Add(UC)? Gerade versucht, zeigt mir dann aber nur den zweiten an.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Dim KundenPanel As New UserControl1
    2. FlowLayoutPanel1.Controls.Add(KundenPanel)
    3. FlowLayoutPanel1.Name = "1"
    4. FlowLayoutPanel1.Location = New Point(20, 40)
    5. FlowLayoutPanel1.Size = New Size(185, 185)
    6. FlowLayoutPanel1.Controls.Add(KundenPanel)
    7. FlowLayoutPanel1.Name = "2"
    8. FlowLayoutPanel1.Location = New Point(245, 40)
    9. FlowLayoutPanel1.Size = New Size(185, 185)


    Wenn ich da dann verstanden habe, kann ich die dann so einfügen wie ich will. Dann muss ich mir mal anschauen, wie ich dann das mit den Button hinbekomme.
    1. Pro Kunden musst Du ein neues User-CE erstellen. Also wenn Du 3 auf einmal hinzufügen willst:

    VB.NET-Quellcode

    1. Dim KundenPanel As New UserControl1
    2. FlowLayoutPanel1.Controls.Add(KundenPanel)
    3. KundenPanel = New UserControl1
    4. FlowLayoutPanel1.Controls.Add(KundenPanel)
    5. KundenPanel = New UserControl1
    6. FlowLayoutPanel1.Controls.Add(KundenPanel)

    2. Location kannst Du weglassen. Die Position des User-CE im FLP legt das FLP ganz allein korrekt fest - wenn es richtig eingestellt ist ;)
    3. Die Location des FLP festzulegen lässt das FLP doch umherspringen. Es sollte immer an seinem Platz bleiben.
    3. Size versteh ich nicht. Warum willst Du den per default rahmenfreien und somit nicht direkt sichtbaren Container in seiner Größe festlegen? Und das mit dem Namen? Wenn, dann legst Du den Namen des User-CE fest. Den des FLP brauchst Du doch gar nicht zu verändern.

    Probier einfach mal nur den in diesem Post o.g. Code. Nix mit Size, Location oder Name
    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.
    @VaporiZed: Wie gesagt, erstmal den Befehl kennen lernen, aber so wie du es mir gerade geschrieben hast, klappt das wunderbar. Eigentlich wie ich es möchte und brauche. Wenn du mir jetzt noch einen Tipp geben könntest, wie ich die einzelnen Elemente (TB und Buttons) ansprechen kann. Bleiben wir bei deinem Beispiel, ich habe ja jetzt 3x je 2 Textboxen und je 3 Buttons. Jetzt muss ich denen ja sagen, was sie später tun sollen.
    Denke dann kann ich beginnen es in mein Projekt dann einarbeiten und schon mal ein fettes Danke für deine Hilfe.
    Dafür ist das Forum da: Um Hilfe zu leisten. Ich bin gespannt, wann uns die Einwände von Rod und EdR um die Ohren fliegen :/
    Um den CEs wie den Buttons nun zu sagen, was sie machen sollen, brauchst Du im Hauptformular fast nix zu machen. Das findet alles im User-CE statt. Also wechsel in den Designer des User-CEs und lege dort den Code fest - wie bei einem normalen Formular. Da Du noch keine Ideen bzgl. der Verknüpfung mit der DataTable hast, hier ein einfaches, ausbaufähiges (!) Beispiel:

    Meine DataTable:


    VB.NET-Quellcode

    1. Public Class CustomerCE
    2. Private _CustomerRow As TdsTest.CustomersRow = Nothing
    3. Public Sub SetLinkedCustomerRow(Row As TdsTest.CustomersRow)
    4. _CustomerRow = Row
    5. LblName.Text = _CustomerRow.Name
    6. TxtNumber.Text = _CustomerRow.Number
    7. TxtDescription.Text = _CustomerRow.Text
    8. End Sub
    9. Private Sub BtnOpenExcel_Click(sender As Object, e As EventArgs) Handles BtnOpenExcel.Click
    10. Process.Start(_CustomerRow.PathToExcelFile)
    11. End Sub
    12. Private Sub BtnOpenAdobe_Click(sender As Object, e As EventArgs) Handles BtnOpenAdobe.Click
    13. Process.Start(_CustomerRow.PathToPdfFile)
    14. End Sub
    15. End Class

    Dass mein User-CE "CustomerCE" heißt, mein tDS "TdsTest" und die darin enthaltene DataTable "Customers" dürfte klar sein, oder? Auch die auf dem User-CE befindlichen CEs sind hier genannt. Im Hauptformular schreibt man irgendwann nach der Befüllung der DataTable:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. AddCustomer(2) 'hier ne beliebige, aber fixe Reihenfolge, die natürlich später durch Deine Auswahl auf Form2 festgelegt wird
    3. AddCustomer(0)
    4. AddCustomer(1)
    5. End Sub
    6. Private Sub AddCustomer(ID As Integer)
    7. Dim NewCustomerPanel As New CustomerCE
    8. NewCustomerPanel.SetLinkedCustomerRow(TdsTest.Customers(ID))
    9. FlowLayoutPanel1.Controls.Add(NewCustomerPanel)
    10. End Sub

    Das Beispiel nimmt an, dass es bereits (mindestens) 3 Rows in der DataTable gibt.

    EDIT: DataTable hinzugefügt.
    Und noch das Ergebnis bei mir:
    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.

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

    Naja wie sagt man so schön, viele Wege führen nach Rom.
    Werde mir das mal genau jetzt anschauen und versuchen an zu wenden. Wird wohl heute aber nix mehr, muss ich wohl bis nächstes Wochenende warten. Blöde Arbeit macht mir da immer ein Strich durch die Rechnung ;)
    @VaporiZed: Kleine Rückmeldung. Nach eine paar Versuchen klappt es jetzt Wunderbar. Genau was ich brauchte. Danke nochmal.

    Ein Problem hatte ich noch. Wenn ich mein Hauptfenster öffne, soll die Usercontrol direkt geladen werden und meine Button sollen eingezeichnet werden. Das mache ich mit einer DGV die in der zweiten Form (Einstellungen). Habe es irgendwie nicht hinbekommen, dass die DGV beim Hauptfensterload als erstes geladen wurde, damit die Abfrage der UserControl seine Daten daraus nehmen kann. Hab es mit einem Workaround gemacht. Beim starten des Programmes (Hauptfenster) öffne ich unsichtbar meine Einstellungsform (da ist das DGV in der Form Load drin) und schließe es direkt wieder. Klappt auch, wird aber wohl nicht die beste Lösung sein. Könnte das Probleme geben oder kann ich es so lassen?
    Sorry, aber mit der Problembeschreibung komm ich überhaupt nicht klar. Kannst Du mit Bildern/Screenshots zeigen, was Du meinst? Und: Was hast Du für Buttons, die eingezeichnet werden sollen?
    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.
    @VaporiZed: Ja dachte mir schon, dass ich es nicht deutlich geschrieben hatte. Also mein Startform-Load sieht so aus
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Haupfenster_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    2. 'Form_Einstellungen.DS_Kunden.ReadXml(Form_Einstellungen._Datafile_DS2.FullName)
    3. 'Form_Einstellungen.PS_kunden_anzeigen()
    4. 'Form_Einstellungen.PS_kunden_Sortierung()
    5. Form_Einstellungen.Show()
    6. Form_Einstellungen.Visible = False
    7. PS_KundenAnzeigen()
    8. Form_Einstellungen.Close()
    9. EndSub


    Das was ich ausgeklammert habe war meine ursprüngliche Idee, hat aber nicht geklappt. So funktioniert es, aber weiß halt nicht ob es da Probleme geben könnte. Er macht ja so wie ich es jetzt programmiert habe, genau das was ich will, war nur die Frage ob ich dadurch Probleme bekommen könnte.

    Damit Stelle ich meine button da:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Sub PS_KundenAnzeigen()
    2. FlowLayoutPanel_Kunden.Controls.Clear()
    3. For i As Integer = 0 To Form_Einstellungen.DGV_Einstellung_Kunde.Rows.Count - 2
    4. For i2 As Integer = 0 To Form_Einstellungen.DGV_Einstellung_Kunde.Rows.Count - 2
    5. If (Form_Einstellungen.DGV_Einstellung_Kunde.Rows(i2).Cells(Form_Einstellungen._dt_kunde_anzeigen).Value.ToString) = "1" And
    6. (Form_Einstellungen.DGV_Einstellung_Kunde.Rows(i2).Cells(Form_Einstellungen._dt_kunde_lb_sichtbar).Value.ToString) = CStr(i) Then
    7. AddKunde(CInt(Form_Einstellungen.DGV_Einstellung_Kunde.Rows(i2).Cells(Form_Einstellungen._dt_kunde_id).Value))
    8. Exit For
    9. End If
    10. Next
    11. Next
    12. End Sub
    13. Private Sub AddKunde(Kundennummer As Integer)
    14. Dim NewCustomerPanel As New UC_Kunden
    15. NewCustomerPanel.SetLinkedCustomerRow(Form_Einstellungen.DS_Kunden.DT_Kunden(Kundennummer))
    16. FlowLayoutPanel_Kunden.Controls.Add(NewCustomerPanel)
    17. End Sub
    Oh no. Nononono.
    @RodFromGermany: Nicht der erste Post, von daher: @Waxweazle: Schau Dir bitte den Thread über das richtige Instanziieren von Formularen an.
    Nächster Punkt: Du packst Daten ins DGV und bastelst mit denen rum. Dafür gibt es das tDS. Das DGV ist zur Anzeige und Dateneingabe vorgesehen, nicht zur Datenmanipulation. Manipuliere die Daten im tDS bzw. in der DataTable. Nicht im DGV!
    Wird das Einstellungsformular überhaupt im Programmverlauf genutzt oder ist das nur für den Anfang da?
    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.
    @VaporiZed: Ich schaue mir das näher an mit den richtigen Instanzen von Formularen.

    Beim Start wird es einmal abgefragt, mit die letzt gewählten Kunden (letztes Programmende) angezeigt werden. Aber es kann auch im Programmverlauf immer aufgerufen werden und die zu anzeigenden Kunden verändert werden.