fortgeschrittene Änderung an TextBoxen

  • VB.NET
  • .NET (FX) 3.0–3.5

Es gibt 30 Antworten in diesem Thema. Der letzte Beitrag () ist von hirnwunde.

    fortgeschrittene Änderung an TextBoxen

    Hi Leute!

    Ich steh mal wieder (wie des öfteren) auf dem Schlauch.



    In den drei Feldern links oben (in der "Startwerte"-GroupBox) werdn Zahlen eingetragen.
    Mit den drei Buttons drunter werden die 20 drunter liegenden Felder folgendermassen befüllt:

    Feld Tool und Rev bleibt immer gleich.
    Das wird nur aus den Startwerd-Feldern kopiert.

    Feld Part wird basierend auf dem Startwert immer um eins erhöht.
    In der ersten Reihe wird also der Startwert kopiert, von da an geht es jeweils um 1 inkrementiert weiter.

    Die vielen Buttons mit der Schere sind dafür gedacht, dass ich den Inhalt der linken drei Textboxen lösche und alles, was darunter ist um ein Feld nach oben verschiebe, sodass keine leere Zeile zurück bleibt.
    Wenn dies geschehen ist, sollte die letze Zeile wieder mit einem fortlaufenden Wert befüllt werden.
    Und das ist der Punkt, an dem ich hänge.

    Ich glaube, dass man das mit sehr viel sich wiederholenden Code lösen könnte.
    Aber ich denke, hier gibt es Profis, die das in ein oder zwei Schleifen lösen können.

    ICH bin jedenfalls (noch?) zu doof dafür ;)

    Würde mich auch über Wegweisende Tipps freuen, an denen ich mich langsam von A nach B zu N hangel ;)

    Die Projekt-Daten habe ich mal angehangen.

    Danke schonmal im Voraus!!

    (Hoffentlich habe ich das verständlich genug erklärt)
    Dateien

    hirnwunde schrieb:

    Aber ich denke, hier gibt es Profis, die das in ein oder zwei Schleifen lösen können.
    Pack jede dieser 20 Zeilen in ein eigenes UserControl und davon die 20 Stück dann in ein FlowLayoutPanel.
    Code ordentlich verteilen und feddich.
    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!
    Ok.

    Na da hab ich ja schonmal einen Humpen an Lernstoff.
    Denn bisher hab ich noch nichts mit UserControls gemacht und mus erstmal schauen, wie und wozu die überhaupt zu gebrauchen sind ;)

    Da hab ich ja erstmal paar Stunden an Lesestoff vor mir ;)

    Danke schonmal, @RodFromGermany! :)
    Uff!

    Nachdem ich mir den Artikel "Erstellen von Visual-Basic-.NET-Steuerelementen" im MSDN zu ca. 75% durchgelesen habe, meine ich, das diese Technik für mich noch zu hoch erscheint, als das ich diese produktiv einsetzen könnte.
    Sicherlich ist es etwas, was ich mir aneignen werde. Nur nicht zum jetzigen Zeitpunkt.

    Da hier viele Sachen behandelt werden, die ich (noch) nicht verstehe, muss ich erstmal zusehen, wie ich das in der jetzigen Form-Variante gebacken bekomme.
    Auch wenn ich dabei auf rekursiven Code zurückgreifen muss.
    Vorerst ist dies aber magels Zeit für das aktuelle Projekt notwendig.

    Wenn man natürlich Deinen Kenntnisstand hat, @RodFromGermany, ist dies keine Option ;)
    Dennoch danke, Rod!! Wie schon erwähnt: die Technik werde ich mir aneignen, da ich beim lesen schon merkte, dass ich dies in anderen -schon fertiggestellten- Projekten ebenso einsetzen kann und später auch werde.

    hirnwunde schrieb:

    wie ich das in der jetzigen Form-Variante gebacken bekomme
    Ich denke, es ist einfacher, wenn Du sofort auf UserControl umsteigst, weil Du allein mit Deinen Indizes bald Fußball spielen kannst.
    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!
    Du hast eine Datenbank, und das sind wohl offensichtlich Datensätze.
    Also bastel ein geeignetes Datenmodell, und zeig den Kram im DGV an. Die Buttons können dan DgvButtonColumns sein.
    kommst du mit typisierten Datasets klar?

    Edit: Und entferne den Deppen-Namespace-GeneralImport: Böse Funktionen vermeiden
    @RodFromGermany
    Die Entscheidung, wie ich morgen weiter mache, mache ich davon abhängig, wie viel ich heut abend von der Technik gelernt habe.
    Es ist halt nicht so einfach, wenn man nie etwas mit Properties, Enumeratoren und diesem Gedöns gemacht hat und sich in der Funktion und Nutzung nicht auskennt.
    Solch eine Row, wie Du sie in deinem lezten Post gezeigt hast, habe ich schon gebastelt.
    Ich habe sie auch schon erstellt und konnte sie (mehrfach) dem FlowPanel hinzufügen.
    Wie ich jetzt allerdings auf die enthaltenen Steuerelemente (TextBoxen und Button) zugreife ist mir noch ein Rätzel ;)

    Edit:
    Jetzt hat es gerade "Klick" gemacht ;)
    Das FlowPanel ist dafür da, dass ich unkompliziert ein komplettes Control löschen kann und die darunter angeordneten Controls nach oben rutschen und ich anschliessend nur ein weiteres hinzufügen muss.
    Man ... toll, wenn man selbst drauf kommt :D

    @ErfinderDesRades
    Jain ;)
    Die werte, die ich in diese Felder eintrage, sollen beim verlassen (KeyDown-Event Enter) in eine DB geschrieben werden.
    Die Logik dazu ist noch nicht eingepflegt.
    Das DGV wäre ja eher etwas, um Daten anzuzeigen und im Nachhinein zu bearbeiten. Oder sehe ichd as falsch?

    Ja. Typisierte DSs sind mir nicht neu.

    Maaaan ... Du weist mich nun schon zum zweiten Mal darauf hin ;)
    Ich habe mir schon ein neues Template erstellt.
    Vergesse nur immer wieder an meinem Arbeits-PC, das auszuwählen. Und erst, wenn man es auswählt, wird beim nächsten erstellen eines neuen Projektes als Standard angeboten.
    Auf meinem Heim-PC ist das schon alles so eingerichtet ;)

    OT!
    Es ist komisch, dass ich meinen Grossteil der Konversationen hier mit euch beiden führe.
    Habe ich nur immer wieder solch knackigen Anfragen, dass nur ihr diese beantworten könnt oder sind die anderen nur zu Faul? ;)

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

    hirnwunde schrieb:

    Wie ich jetzt allerdings auf die enthaltenen Steuerelemente (TextBoxen und Button) zugreife ist mir noch ein Rätzel
    Mehrere UserControls packst Du in ein Array davon, über dieses (per Index) kommst Du an das Control und dort an dessen Elemente.
    Gugst Du auch hier.
    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!

    RodFromGermany schrieb:

    Mehrere UserControls packst Du in ein Array davon

    Ja. Genau!

    Bitte was?! ;)
    Das meinte ich vorhin mit "Kenntnisstand".
    Da ist die Schere bei uns sehr weit auseinander.

    Klar. Ich weis, was ein Array ist und wie ich dieses verwende.
    Wie ich allerdings ein UserControl dort unterbringen soll und dann auf das einzelne Control zugreife, kann ich noch nicht sehen.
    Aber ich schaue mir den Code und dessen Kommentare an, welchen Du gepostet hast.

    Ich habe gerade heraus bekommen, dass man ja auf die einzelnen Elemente über das UserControl selbst zugreifen kann.
    Mein UserControl habe ich UC_BauteilReihe genannt.
    Wenn ich dies nun in dem FlowPanel hinzufüge, bekommt dies ja fortlaufende Nummern angehangen, wie bei TextBoxen und dem anderen Geschnodder ja auch.
    Mit UC_BauteilReihe.tb_rev_01.Text kann ich nun also auch die TextBoxen beschreiben/auslesen.
    Allerdings habe ich noch keine Möglichkeit gefunden, wie ich auf das Event vom Button reagieren kann.
    Mein Versuch mit Private Sub UCBtnClick(sender As System.Object, e As System.EventArgs) Handles UC_BauteilReihe1.btn_cut.Click funktioniert schonmal nicht ;)

    Aber da kommen wohl die Properties ins spiel, die ich der Aussenwelt (ausserhalb der UserControl) verfügbar machen muss ... mal schauen :)

    hirnwunde schrieb:

    Es ist komisch, dass ich meinen Grossteil der Konversationen hier mit euch beiden führe.
    Habe ich nur immer wieder solch knackigen Anfragen, dass nur ihr diese beantworten könnt oder sind die anderen nur zu Faul?

    Du hast eben das Glück immer wieder das Thema Datenhaltung/Datenbänkerei anzukratzen, und dafür gibt es, zumidnest was ich bisher gesehen habe, keinen Besseren als @ErfinderDesRades. Fast jedes verlinkte Datenbanktutorial geht auf einen seiner Threads oder Posts zurück. Und der Rest schient wohl nicht derart aktiv zu sein wie @RodFromGermany :P die - derzeit - 31K Posts müssen ja auch irgendwo her kommen.

    RodFromGermany schrieb:

    UserControls ... Array ... über dieses ... kommst Du an das Control und ... dessen Elemente.

    oder anders gesagt, du erzeugst ein Array vom Typ deiner UserControls und packst die dort alle rein. Danach kannst wie bei jedem anderen Array dann die UserControls erreichen.

    hirnwunde schrieb:

    Die werte, die ich in diese Felder eintrage, sollen beim verlassen (KeyDown-Event Enter) in eine DB geschrieben werden.
    Die Logik dazu ist noch nicht eingepflegt.
    Das DGV wäre ja eher etwas, um Daten anzuzeigen und im Nachhinein zu bearbeiten. Oder sehe ichd as falsch?
    Mit einem DGV kann man auch Datensätze zufügen - normalerweise besser als mit 20 UserControls.
    Und hättest du ein typisiertes Dataset, dann wäre die zu hinterlegende Logik vollkommen trivial.
    Auch das Abspeichern wäre trivial.
    Das Problem bei den meisten Datenverarbeitungs-Noobs ist, dass sie Daten verarbeiten wollen, aber haben gar kein Datenmodell.
    Das ist wie Wasser holen gehen und den Eimer vergessen.
    Und Zeitmangel ist dann echt schlecht, weil dann versucht man mit Plastiktüten, Taschentüchern und was man sonst noch auf die schnelle findet irgendwas zu improvisieren.
    Was letztendlich eher Zeit vergeudet denn einspart.

    hirnwunde schrieb:

    Bitte was?
    Sieh Dir mal dies Projekt an.
    TestMyUserControl.zip
    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!
    @ErfinderDesRades
    Huch. Ich glaube, ich habe da etwas den Mund zu voll genommen.
    Nein. Ich habe bisher keine Erfahrug mit typisierten DSs.
    Ich habe es mit nicht typisierten DSs verwechselt, in denen bei der Column-Erstellung dem Feld ein Typ zugewiesen wird.
    Ein typisiertes DS ist da nochmal ein ganz anderes Kaliber.
    Wie ich dieses mit meiner MySQL-Datenbank verbinde, weis ich nicht.
    Und jetzt noch eine Baustelle anfangen, wage ich nicht ;)

    Wie ich schonmal eingangs erwähnte: Ich muss mir mal einen (guten) Lehrgang heraus suchen. Vieles schaff ich zwar autodidaktisch. Viele andere Sachen aber eben nicht.
    Und wie ich das so sehe ist das typisierte DataSet eines der Themen, welches ich nicht so schnell allein erlernen werde ;)

    @RodFromGermany
    Danke für das Beispiel-Projekt!
    Das hilft mir ungemein!
    Mit diesem werde ich erstmal -um das Verständis zu erweitern- ein wenig rumspielen.
    Danke nochmal!
    @RodFromGermany
    Danke!!

    Ich hab jetzt mal den Abend über mit deinem beispielprojekt herumgespielt und bin schon recht weit ;)

    Das UserControl habe ich an meine Bedürfnisse angepasst.
    Diesem habe ich neue Events & Properties hinzugefügt.
    Ich kann nicht sagen, dass ich alles verstanden habe.aber es funktioniert bisher ;)

    Zumindest bis zu einem bestimmten Punkt ;)

    Wenn das Programm startet, werden 20 Controls erzeugt und im FlowPanel eingefügt.

    VB.NET-Quellcode

    1. Private Sub Form1_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
    2. For i = 0 To 19
    3. Dim uc = New MyUserControl
    4. uc.Index = i
    5. AddHandler uc.btn_cut_Click, AddressOf MyButtonClickHandler
    6. AddHandler uc.tb_lw_KeyDown, AddressOf LwKeyDownHandler
    7. AddHandler uc.tb_cw_KeyDown, AddressOf CwKeyDownHandler
    8. Me.MyUserControls.Add(uc)
    9. Me.FlowLayoutPanel1.Controls.Add(uc)
    10. Next
    11. End Sub


    Der UserControl habe ich neue Events spendiert (denn ich will ja auf die KeyDown's der Textbox reagieren)

    VB.NET-Quellcode

    1. Public Class MyUserControl
    2. Public Event btn_cut_Click(sender As Object, e As EventArgs)
    3. Public Event tb_lw_KeyDown(sender As Object, e As EventArgs)
    4. Public Event tb_cw_KeyDown(sender As Object, e As EventArgs)
    5. Public Property Index As Integer
    6. Public WriteOnly Property MyTool As String
    7. Set(value As String)
    8. Me.tb_tool.Text = value
    9. End Set
    10. End Property
    11. Public WriteOnly Property Myrev As String
    12. Set(value As String)
    13. Me.tb_rev.Text = value
    14. End Set
    15. End Property
    16. Public WriteOnly Property Mypart As String
    17. Set(value As String)
    18. Me.tb_part.Text = value
    19. End Set
    20. End Property
    21. Public WriteOnly Property MyLW As String
    22. Set(value As String)
    23. Me.tb_lw.Text = value
    24. End Set
    25. End Property
    26. Public WriteOnly Property MyCW As String
    27. Set(value As String)
    28. Me.tb_cw.Text = value
    29. End Set
    30. End Property
    31. Private Sub btn_cutClick(sender As Object, e As EventArgs) Handles btn_cut.Click
    32. RaiseEvent btn_cut_Click(Me, EventArgs.Empty)
    33. End Sub
    34. Private Sub tb_lwKeyDown(sender As Object, e As EventArgs) Handles tb_lw.KeyDown
    35. RaiseEvent tb_lw_KeyDown(Me, EventArgs.Empty)
    36. End Sub
    37. Private Sub tb_cwKeyDown(sender As Object, e As EventArgs) Handles tb_cw.KeyDown
    38. RaiseEvent tb_cw_KeyDown(Me, EventArgs.Empty)
    39. End Sub
    40. End Class

    Um die KeyDown's abzufangen, brauch ich aber ansatt der EventArgsKeyEventArgs ...
    Und da fängt es an, bei mir zu stocken.

    Wenn ich

    VB.NET-Quellcode

    1. Public Event tb_lw_KeyDown(sender As Object, e As KeyEventArgs)
    2. Public Event tb_cw_KeyDown(sender As Object, e As KeyEventArgs)

    und

    VB.NET-Quellcode

    1. Private Sub tb_lwKeyDown(sender As Object, e As KeyEventArgs) Handles tb_lw.KeyDown
    2. RaiseEvent tb_lw_KeyDown(Me, KeyEventArgs.Empty)
    3. End Sub
    4. Private Sub tb_cwKeyDown(sender As Object, e As KeyEventArgs) Handles tb_cw.KeyDown
    5. RaiseEvent tb_cw_KeyDown(Me, KeyEventArgs.Empty)
    6. End Sub

    schreibe, bekomme ich den Fehler:
    "Option Strict On" lässt keine impliziten Konvertierungen von System.EventArgs in System.Windows.Forms.KeyEventArgs zu.

    Ich wundere mich, wo hier EventArgs definiert sind ... denn die Public Event's sind ja KeyEventArgs ...
    Ich habe mal das Fehlerbehaftete Projekt angehangen ;)
    Dateien

    hirnwunde schrieb:

    VB.NET-Quellcode

    1. RaiseEvent tb_lw_KeyDown(Me, KeyEventArgs.Empty)
    Da musst Du die im KeyEventArgs-Parameter vorhandene Information einfach durchreichen:

    VB.NET-Quellcode

    1. RaiseEvent tb_lw_KeyDown(Me, e)
    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!
    Super!
    Das funktioniert jetzt wunderbar.

    VB.NET-Quellcode

    1. Private Sub tb_lwKeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles tb_lw.KeyDown
    2. If e.KeyCode = Keys.Enter Then
    3. RaiseEvent tb_lw_KeyDown(Me, e)
    4. End If
    5. End Sub
    6. Private Sub tb_cwKeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles tb_cw.KeyDown
    7. If e.KeyCode = Keys.Enter Then
    8. RaiseEvent tb_cw_KeyDown(Me, e)
    9. End If
    10. End Sub


    Langsam macht es Spass, mit dem UC zu "spielen" ;)
    Mir ist das suspekt, weil
    1. tb_cw_KeyDown als Name eines öffentlichen Klassenmember ist totale Katastrophe: Finde EventNamen, die eine Aussage treffen, und zwar eine korrekte
    2. tb_cw_KeyDown ist neben Unverständlichkeit sogar eine Falsch-Aussage. Denn es wird nicht wirklich das KeyDown gesendet, sondern nur bei [Enter] wird was gesendet.
    3. die beiden Methoden sehen total gleich aus. Ich weiß nicht, was die machen sollen, aber wenn 2 Methoden gleich aussehen, dann sollte man gucken, ob man sie zu einer einzigen zusammenfassen kann.
      Vlt. sollen diese Events ja informieren, dass in einer von 2 Textboxen eine Eingabe abgeschlossen ist? Da fiele mir schon ein wesentlich besseres Design für ein - wenn dem so wäre.
    Das mit dem falschen Bezeichner fiel mir auch auf, als ich weitere Aenderungen am Code machte.
    Dieses ist mittlerweile schon wieder behoben. Dennoch danke fuer den Hinweis!

    VB.NET-Quellcode

    1. Private Sub tb_lwEnterDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles tb_lw.KeyDown
    2. If e.KeyCode = Keys.Enter Then
    3. RaiseEvent tb_lw_EnterDown(Me, e)
    4. End If
    5. End Sub
    6. Private Sub tb_cwEnterDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles tb_cw.KeyDown
    7. If e.KeyCode = Keys.Enter Then
    8. RaiseEvent tb_cw_EnterDown(Me, e)
    9. End If
    10. End Sub

    Und ja. Es soll damit ins naechste Feld gewechselt werden.
    Das mache ich in der Form:

    VB.NET-Quellcode

    1. Private Sub LwEnterDownHandler(sender As Object, e As KeyEventArgs)
    2. Dim uc As MyUserControl = DirectCast(sender, MyUserControl)
    3. If uc.Index = lastUC Or uc.Index = lastActiveUC Then
    4. MyUserControls(0).tb_cw.Focus()
    5. Else
    6. MyUserControls(uc.Index + 1).tb_lw.Focus()
    7. End If
    8. End Sub
    9. Private Sub CwEnterDownHandler(sender As Object, e As KeyEventArgs)
    10. Dim uc As MyUserControl = DirectCast(sender, MyUserControl)
    11. If uc.Index = lastUC Or uc.Index = lastActiveUC Then
    12. MessageBox.Show("Ende!")
    13. Else
    14. MyUserControls(uc.Index + 1).tb_cw.Focus()
    15. End If
    16. End Sub

    dazu gibts noch die beiden Handler, die beim Shown-Event erstellt werden

    VB.NET-Quellcode

    1. AddHandler uc.tb_lw_EnterDown, AddressOf LwEnterDownHandler
    2. AddHandler uc.tb_cw_EnterDown, AddressOf CwEnterDownHandler


    In wie weit man zwei zwei Events von zwei Controls in einer Methode auffaengt, weis ich leider nicht.
    Kann amn einfach ein zweites Event an Handles anhaengen?
    Ginge vielleicht Handles tb_cw.KexDown, tb_lw.KeyDown?

    Aber Ganz so gleich sind die Methoden ja nicht. Denn es sind ja zwei verschiedene Textboxen, die das Event triggern.
    Und ich reagiere auch unterschiedlich bei den beiden Boxen.
    Wenn das Event vom letzten (aktiven) tb_lw kommt wechselt der Focus zum ersten tb_cw.
    Wenn es vom letzten tb_cw kommt, soll spaeter ein Dialog zum kompletten zuruecksetzen der Form erscheinen.

    hirnwunde schrieb:

    zwei Events von zwei Controls in einer Methode auffaengt
    ganz einfach:

    VB.NET-Quellcode

    1. AddHandler uc.tb_lw_EnterDown, AddressOf MyEnterDownHandler
    2. AddHandler uc.tb_cw_EnterDown, AddressOf MyEnterDownHandler
    und dann im Handler den Parameter Sender abfragen.
    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!

    hirnwunde schrieb:

    Dieses ist mittlerweile schon wieder behoben.
    ist es nur teilweise.
    Nachwievor heisst das Event, was geraist wird tb_lw_EnterDown - was soll das sein, ein tb_lw?

    Wenn lw "LeistungsWert" bedeutet, dann könnte man das Event sinnig benennen mit LeistungsWertInputDone, und dann würde das Event so heissen wie für was es da ist, und Code würde sich malwieder selbst erklären.