ChangeEvent von mehreren Textboxen

  • VB.NET

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

    ChangeEvent von mehreren Textboxen

    Hallo Leute
    Ich habe mir eine kleine Sub geschrieben, um zu prüfen ob der Inhalt einer Textbox numerisch ist: (Name der Textbox ist TB95Min)

    Quellcode

    1. Dim aenderung As Integer
    2. Integer.TryParse(TB95Min.Text, aenderung)
    3. If aenderung = 0 Then
    4. 'Wenn nicht numerisch
    5. Else
    6. 'wenn numerisch
    7. Exit sub

    Den Rest des Codes erspare ich euch mal, denn er hat nichts mit dem eigentlichen Problem zu tuen (wenn er benötigt werden sollte, reiche ich ihn aber gerne nach)

    Nun möchte ich die gleiche Sub für alle meine Textboxen im change Event verwenden:

    Quellcode

    1. Private Sub TBAbkuehlzeit_KeyUp(sender As Object, e As KeyEventArgs) Handles TB95Sek.KeyUp, TB95Min.KeyUp, TB90Sek.KeyUp, TB90Min.KeyUp, TB85Sek.KeyUp, TB85Min.KeyUp, TB80Sek.KeyUp, TB80Min.KeyUp, TB75Sek.KeyUp, TB75Min.KeyUp, TB70Sek.KeyUp, TB70Min.KeyUp, TB65Sek.KeyUp, TB65Min.KeyUp, TB60Sek.KeyUp, TB60Min.KeyUp, MyBase.KeyUp
    2. Dim aenderung As Integer
    3. Integer.TryParse(sender.Text, aenderung)
    4. If aenderung = 0 Then
    5. Else
    6. End if

    Bei dieser Sub erhalte ich aber den Fehler, dass Option Strict On spätes binden nicht zulässt.
    Also habe ich als erste Codezeile folgendes eingefügt:

    Quellcode

    1. Dim TB As TextBox = sender

    Jedoch erhalte ich dann den Fehler:
    Fehler BC30512 "Option Strict On" lässt keine impliziten Konvertierungen von "Object" in "TextBox" zu.

    Ich verstehe aber an dieser Stelle nicht, was ich konvertieren soll.
    Denn die erstellte Variable TB ist eine Textbox, und der Sender doch auch?

    Oder bin ich komplett auf dem Holzweg?

    DerSmurf schrieb:

    Ich verstehe aber an dieser Stelle nicht, was ich konvertieren soll.

    Wenn du weist, dass all deine Sender Textboxen sind, dann caste wie folgt:

    VB.NET-Quellcode

    1. Dim tbx = DirectCast(sender, Textbox)
    2. Dim aenderung As Integer
    3. Integer.TryParse(tbx.Text, aenderung)
    4. '...

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

    DerSmurf schrieb:

    um zu prüfen ob der Inhalt einer Textbox numerisch ist
    verwendest Du zwar Integer.TryParse, aber falsch. Du prüfst, ob aus dem Text eine Zahl entsteht. Und wenn diese Zahl Null ist, dann gehst Du davon aus, dass es keine Zahl war. Wenn Du aber in die TextBox Null eingibst, dann was? Diese als Text weiterinterpretieren? WelcherTypAuchImmer.TryParse hat einen Boolean-Rückgabewert, es meldet Dir also, ob eine Umwandlung möglich war. Nutze diesen.

    @VB1963: tbx kann man aber nicht zu einem Integer parsen ;) Nur deren Text-Property.

    VB1963 schrieb:

    Wenn du weist, dass all deine Sender Textboxen sind
    und er weiß, dass es nicht so ist, da am Ende der Handles-Zeile MyBase.KeyUp steht. Das muss getrennt behandelt werden. Also am besten in eine Sub auslagern und diese dann aufrufen, indem man den entsprechenden Text übergibt. Aber hey, welcher Text soll denn bitte von dem Form geparst werden? Oder was ist MyBase?
    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 3 mal editiert, zuletzt von „VaporiZed“ ()

    @DerSmurf Wenn Du das KeyPress-Event der Textbox abonierst und dort alle Nicht-Num-Tasten abfängst, ist gesichert, dass in der Textbox nur richtige Zeichen stehen.

    VB.NET-Quellcode

    1. Private Sub TextBox1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TextBox1.KeyPress
    2. If Not Char.IsDigit(e.KeyChar, 0) Then
    3. e.Handled = True
    4. End If
    5. End Sub
    Wenn Du editieren wilst, musst Du die Cursortasten wieder zulassen.
    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!
    SO, danke ihr lieben :)

    Ich glaube so wäre mein Code jetzt korrekt (zumindest läuft er - und ich habe den TryParse eintrag zuende gelesen...)
    DirectCast habe ich ebenfalls in der MSDN nachgeschaut und verstanden.
    1. der Code
    Spoiler anzeigen

    Die Variable Abkuehlzeitgeaendert ist eine globale boolean, welche nach Klick auf einen Speichernbutton prüfen soll, ob die Werte in My.Settings gespeichert werden oder nicht:

    Quellcode

    1. Private Sub TBAbkuehlzeit_KeyUp(sender As Object, e As KeyEventArgs) Handles TB95Sek.KeyUp, TB95Min.KeyUp, TB90Sek.KeyUp, TB90Min.KeyUp, TB85Sek.KeyUp, TB85Min.KeyUp, TB80Sek.KeyUp, TB80Min.KeyUp, TB75Sek.KeyUp, TB75Min.KeyUp, TB70Sek.KeyUp, TB70Min.KeyUp, TB65Sek.KeyUp, TB65Min.KeyUp, TB60Sek.KeyUp, TB60Min.KeyUp
    2. Dim tbx = DirectCast(sender, TextBox)
    3. Dim ergebnis As Integer
    4. Dim aenderung As Boolean = Int32.TryParse(tbx.Text, ergebnis)
    5. If aenderung = True Then
    6. 'Zahl eingegeben
    7. lblAbkuehlzeit.Text = ""
    8. Abkuehlzeitgeaendert = True
    9. Else
    10. 'keine Zahl
    11. lblAbkuehlzeit.Text = "nur Zahlen"
    12. Abkuehlzeitgeaendert = False
    13. End If
    14. End Sub


    2. Zum MyBase KeyUp
    Ich habe keine Ahnung warum das da steht. Habe alle Textboxen markiert in den Ereignissen das KeyUp ausgewählt und den Namen TBAbkuehlzeit vergeben.
    Beschreibt My.Base KeyUp das KeyUp Event der Form selber? Dann habe ich mich wohl verklickt :o)
    Habs nun einfach weggelöscht.
    Also noch mal zur Sicherheit: Ich brauche nur die KeyUp Events der Textboxen, um dort auf numerische Eingabe zu prüfen.

    3. Der Ansatz von RodFromGermany gefällt mir auch. Finde ich eigentlich logischer als meinen.
    Statt den vorhandenen und beliebigen String auf "numerischkeit" zu prüfen, verhindere ich einfach nicht numerische Eingaben.
    "Mein" Code zu diesem Ansatz sieht wie folgt aus (erstmal nur für eine Textbox - ist für mich leichter - den Rest mache ich später)
    Spoiler anzeigen

    Quellcode

    1. Private Sub TB95Min_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TB95Min.KeyPress
    2. If Not Char.IsDigit(e.KeyChar, 0)
    3. lblAbkuehlzeit.Text = "nur Zahlen"
    4. Abkuehlzeitgeaendert = False
    5. e.Handled = True
    6. Else
    7. lblAbkuehlzeit.Text = ""
    8. Abkuehlzeitgeaendert = True
    9. End If
    10. End Sub

    Allerdings muss ich ja noch Backspace hinzufügen.
    Hierfür muss ich aber doch ASC verwenden - also die Prüfung wie folgt umstellen:

    Quellcode

    1. 'nicht numerisch und ungleich ASC(8)
    2. If Not Char.IsDigit(e.KeyChar, 0) AndAlso Not (Asc(e.KeyChar) = 8 Then

    Aber zu diesem ASC gibt es laut dem Forum hier keine VB.Net Alternative, was mich dazu zwingt den Visual Basic Namespace wieder einzuschalten - das möchte ich nicht - sonst würde ich permanent nur meine VBA Befehle verwenden und werde nicht mehr gezwungen zu googlen, wenn Visual Studio mein VBA gecode rot unterkringelt.


    4. noch eine Frage an RodformGermany (darf ich in Zukunft Rod sagen?)
    Du nutzt das KeyPress Event. Warum? Also macht es einen Unterschied, ob ich die Sub losfeuer, wenn die Taste gedrückt wird, oder ob sie startet, wenn die Taste wieder oben ist (wie bei mir?)
    Da meine ich das NumericUpDown-Control, das auch in der Toolbox angeboten wird. Bei diesem sind nur nummerische Eingaben erlaubt.
    Der Unterschied vom KeyUp- und KeyPressEvent liegt an den verschiedenen EventArgs-Argumenten der Signatur, die ausgewertet werden können... Beim KeyPressEvent kannst du eine Handled-Eigenschaft benutzen, die Tasteneingaben zulässt oder nicht - das bei der anderen nicht möglich ist...
    @DerSmurf Du hast den Sinn meines Codes nicht ganz verstanden.
    Ein Else ist nicht erforderlich, denn das IsDigit macht das doch, und wenn eine falsche Taste gedrückt wird, passiert einfach nix.
    Da ist es nicht erforderlich, dass Du meldest "Falsche Taste gedrückt".
    Du kannst die Key-Codes der Tasten abfragen:
    Nicht If (Asc(e.KeyChar) = 8) Then sondern If (e.KeyChar = Chars.WhatEver) Then.
    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!
    Ah, danke Rod.
    Das werde ich testen und meinen Code dann prästentieren.
    Deinen Code habe ich schon verstanden - einfach alle nicht gewünschten Tasten "sperren".
    Wie gesagt, finde ich das ja auch sinnvoller, als meinen Ansatz.

    Allerdings benötige ich den Else Zweig, also eine korrekte Eingabe, um der globalen Variablen "Abkuehlzeitgeaendert" den Wert True zuzuweisen.
    Nach einem Klick auf den Button speichern, werden alle Einstellungen dieser Form in My.Settings gespeichert, um nicht die 18 Textboxen um die es hier geht sinnlos zu speichern (wenn nix geändert wird), habe ich den Else Zweig verwendet.
    Oder kann ich mir das schenken, und einfach speichern, egal ob es eine Änderung gibt, oder nicht?

    DerSmurf schrieb:

    egal ob es eine Änderung gibt, oder nicht?
    Wenn Du einen Dateiinhalt mit sich selbst überschreibst, ist das egal, wenn es hinreichend flott geht.
    Vielleicht erklärst Du uns zunächst, was es mit diesen 18 Controls auf sich hat.
    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!
    Ja sorry, ein bisschen mehr Info wäre wohl hilfreich gewesen :o)
    Ich bastel gerade als Testprogramm an einem "Tea Timer"
    Dieses werde ich sobald ich fertig bin hochladen, mit bitte um Bewertung :o)
    Hier spiele ich einfach mit dem Aufruf von verschiedenen Formen, My.Settings, Timern und der gleichen rum.
    Auch eine Datagridview mit angebundener csv zum Speichern von verschiedenen Tees mit Temperaturen und Ziehzeiten will ich noch einbauen.
    Letzlich sind zwei Zeiten einstellbar. 1. Die Wassertemperatur, bei der der Tee ins Wasser kommt und 2. die Ziehzeit.
    Also im Programm stelle ich z.B. ein 90° und Ziehzeit 2 minuten.
    Nach einem Klick auf Start läuft Timer 1 - bis das Wasser 90° hat, nach Timerablauf erscheint eine Meldung - nach Klick auf OK, läuft Timer2, die Ziehzeit.
    Diese Funktionalität ist gegeben und alles geht. Nun bin ich an den Einstellungen.
    Hierzu gibt es eine eigene Form, auf der bisher folgendes enthalten ist (bitte nicht über Sinn- oder Unsinn dieser Einstellungen in einem Tea Timer nachdenken, das Programm dient mir als Übung)

    1. Chechbox - Timer immer im Vordergrund anzeigen

    2. Numeric Up and down - Einstellungen um welches Intervall sich die Ziehzeit ändert

    3. die 18 Textboxen - jeweils 2 Textboxen (Minuten und Sekunden) für die verschiedenen Temperaturen.
    95, 90, 85, 80, 75, 70, 65, 60 Grad. Mit diesen Textboxen lässt sich die Zeit einstellen die das Wasser braucht zum Abkühlen auf die entsprechende Temperatur. Der Inhalt der Textboxen (also Minuten und Sekunden) wird in Sekunden umgerechnet und in My.Settings gespeichert (jeweils ein Wert pro Temperatur) - ich hoffe das war verständlich :o)

    4. ein speichern Button: Die Sub hierhinter speichert den Inhalt aus 1. und 2. in My.Settings. Darüber hinaus gibt es die oben erwähnte globale Variable, die prüft ob eine Temperatur geändert wurde und nur dann die Werte entsprechend speichert.
    Hier die speichern Sub (falls es eine Rolle spielt)

    Quellcode

    1. 'Klick Events Buttons
    2. Private Sub btnSpeichern_Click(sender As Object, e As EventArgs) Handles btnSpeichern.Click
    3. 'Speichern in My.Settings
    4. 'Immer im Vordergrund
    5. My.Settings.Vordergrund = cBVordergrund.Checked
    6. 'Ziehzeitintervall
    7. My.Settings.Zeitintervall = NumUpZiehzeit.Value
    8. 'Abkuehlzeiten nur speichern, wenn globale boolean True
    9. If Abkuehlzeitgeaendert = True Then
    10. My.Settings.Temp95 = Integer.Parse(TB95Min.Text) * 60 + Integer.Parse(TB95Sek.Text)
    11. My.Settings.Temp90 = Integer.Parse(TB90Min.Text) * 60 + Integer.Parse(TB90Sek.Text)
    12. My.Settings.Temp85 = Integer.Parse(TB85Min.Text) * 60 + Integer.Parse(TB85Sek.Text)
    13. My.Settings.Temp80 = Integer.Parse(TB80Min.Text) * 60 + Integer.Parse(TB80Sek.Text)
    14. My.Settings.Temp75 = Integer.Parse(TB75Min.Text) * 60 + Integer.Parse(TB75Sek.Text)
    15. My.Settings.Temp70 = Integer.Parse(TB70Min.Text) * 60 + Integer.Parse(TB70Sek.Text)
    16. My.Settings.Temp65 = Integer.Parse(TB65Min.Text) * 60 + Integer.Parse(TB65Sek.Text)
    17. My.Settings.Temp60 = Integer.Parse(TB60Min.Text) * 60 + Integer.Parse(TB60Sek.Text)
    18. End If
    19. Me.Close()
    20. End Sub


    Mein Gedanke war nun, das eine Prüfung, ob ich diese 8 Werte speichern muss, sinnvoll sein könnte.
    Also ich wollte einfach ein sinnloses speichern in den Settings vermeiden, fand es irgendwie unsauber die Daten zu speichern, obwohl es nix zu speichern gibt.
    Hier lasse ich mich aber natürlich gerne belehren.

    edit:
    Folgender Fehler erscheint, wenn ich versuche auf "backspace" zu prüfen If (e.KeyChar = Chars.8) Then:

    Fehler BC30451 "Chars" wurde nicht deklariert. Aufgrund der Schutzstufe ist unter Umständen kein Zugriff möglich.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DerSmurf“ ()

    Heyho.
    Das die Settings automatisch gespeichert werden, wenn die Form geschlossen wird, ist mir bewusst.
    Das hatten wir ja schonmal.

    Es geht hier ja aber darum, ob ich den Eigenschaften (sind das Eigenschaften?) in My.Settings einen neuen Wert zuweise, oder nicht.

    Quellcode

    1. If Abkuehlzeitgeaendert = True Then
    2. My.Settings.Temp95 = Integer.Parse(TB95Min.Text) * 60 + Integer.Parse(TB95Sek.Text)
    3. My.Settings.Temp90 = Integer.Parse(TB90Min.Text) * 60 + Integer.Parse(TB90Sek.Text)
    4. My.Settings.Temp85 = Integer.Parse(TB85Min.Text) * 60 + Integer.Parse(TB85Sek.Text)
    5. My.Settings.Temp80 = Integer.Parse(TB80Min.Text) * 60 + Integer.Parse(TB80Sek.Text)
    6. My.Settings.Temp75 = Integer.Parse(TB75Min.Text) * 60 + Integer.Parse(TB75Sek.Text)
    7. My.Settings.Temp70 = Integer.Parse(TB70Min.Text) * 60 + Integer.Parse(TB70Sek.Text)
    8. My.Settings.Temp65 = Integer.Parse(TB65Min.Text) * 60 + Integer.Parse(TB65Sek.Text)
    9. My.Settings.Temp60 = Integer.Parse(TB60Min.Text) * 60 + Integer.Parse(TB60Sek.Text)
    10. End If


    Sol dieser Block immer laufen, oder eben nur, wenn in den Textboxen etwas geändert wurde (dann ist Abkuehlzeitgeandert = True), dafür brauche ich ja aber den Else Zweig im KeyPress Event.
    Guten Morgen
    Ich glaube wir reden aneinander vorbei, oder ich verstehe dich nicht :)

    Das speichern der Settings beim schließen der Anwendung ist für mich das was passiert, wenn ich My.Settings.Save() verwende.
    Wenn ich die Einstellungen entsprechend setzte (bzw. auf Default lasse), erfolgt dieses Speichern aber beim schließen der Form automatisch.

    Mit geht es jetzt aber darum, wann ich den Settings: Temp95 - Temp60 neue Werte zuweise.
    Einfach immer, wenn ich auf den speichern Button drücke, oder eben nur dann, wenn sich auch ein Wert geändert hat.
    Bedenke, dass man die Settings auch an deine Textboxen binden kann. Aber da kannst du nur an die .Text-Eigenschaft der Textboxen binden...
    D.h., die Settings müssen einen Stringdatentyp aufweisen! Dann kannst du dir obigenen Code sparen. Besser noch, wenn du nur numerische Eingaben haben möchtest, dass du meine weiter oben genannten NUD's verwendest. Weil diese kannst du mit Double binden...
    Und du brauchst dich an das Speichern erst gar nicht kümmern - das passiert von selbst.
    Wenn der Haken drin ist, braucht man mit My.Settings.Save doch gar nicht zu arbeiten.
    Wenn man z.B. sagt: My.Settings.CriticalDayCount = 10 und dann es wieder aufruft oder ein anderes Form instanzziert, aufruft und da nach My.Settings.CriticalDayCount fragt, bekommt man doch auch 10 zurück. Wozu dann also Save?
    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.