NumericUpDown alter Wert wenn Feld leer

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

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    NumericUpDown alter Wert wenn Feld leer

    Hallo Zusammen,

    ich habe ein kleines Problem, in meinem VB-Projekt.
    Mir ist gerade aufgefallen, dass wenn ich einen Wert aus einer NumericUpDown entferne so dass das Feld leer ist und dann mit ".Value" den Wert ermittele, immer noch der Wert vor dem Löschen ermittelt wird.


    Kleines Beispiel:
    Ich habe ein Feld NumericUpDown1. In dieses trage ich den Wert 5 ein und klicke auf unten stehenden Button. Dann erscheint der Wert 5.
    Gehe ich nun in das Feld NumericUpDown1, markiere den Wert und lösche ihn und klicke dann auf den Button, erscheint immernoch der Wert 5.
    Dies ändert sich erst dann, wenn ich in NumericUpDown1 eine '0' eintrage.

    VB.NET-Quellcode

    1. Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
    2. Dim cVal As Decimal
    3. cVal = NumericUpDown1.Value
    4. MsgBox(cVal.ToString())
    5. End Sub


    Das Verhalten ist mir total suspekt. Ich hätte erwartet, dass mir der ".Value" den Wert zurück liefert, der darin steht oder falls leer halt eine 0.
    Muss ich jetzt überall im Code noch prüfen, ob ".Text" leer ist und dann den ".Value" im Code auf 0 setzen? Da werde ich ja nicht mehr fertig... :huh:

    Habt ihr dieses Problem auch? Falls ja, wie habt ihr es gelöst?

    Vielen Dank für eure Antworten. :thumbsup:

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

    Ich habe jetzt für mich eine Lösung gefunden, die für alles was ich zukünftig anlege funktionieren sollte.
    "Mein Glück" ist, dass bei mir jede Form bei ihrer Anlage von einer anderen Klasse erbt um diverse Dinge zu steuern.

    In der Form selbst rufe ich beim Verlassen aller NumericUpDowns die Methode "NumericUpDownExit" auf, die erstmal die 0 einträgt und dann die "_NumericUpDownExit" aufruft, die in der Form selbst überschrieben wird, falls ich beim Verlassen der Controls noch etwas anderes Steuern möchte.

    VB.NET-Quellcode

    1. Public Overridable Function NumericUpDownExit(ByRef cNUD As System.Windows.Forms.NumericUpDown) As Integer
    2. Dim rCode As Integer
    3. If DirectCast(cNUD, System.Windows.Forms.Control).Text = "" Then
    4. cNUD.Value = 0
    5. End If
    6. rsc = _NumericUpDownExit(cNUD)
    7. Return rCode
    8. End Function
    9. Public Overridable Function _NumericUpDownExit(ByRef cNUD As System.Windows.Forms.NumericUpDown) As Integer
    10. Dim rCode As Integer
    11. 'Do some stuff
    12. Return rCode
    13. End Function


    Trotzdem habe ich das Problem für alle alten NumericUpDowns. Das Nachzupflegen wird ein schöner Aufwand... Falls jemand noch eine gute Idee haben sollte, gerne her damit.

    Im Code der eigentlichen Form sieht es dann folgendermaßen aus:

    VB.NET-Quellcode

    1. Private Sub NUD_Leave(sender As Object, e As EventArgs) Handles NumericUpDown1.Leave, NumericUpDown2.Leave, NumericUpDown3.Leave
    2. Dim rCode As Integer
    3. Dim nud As NumericUpDown = CType(sender, NumericUpDown)
    4. rCode = wcl.NumericUpDownExit(nud)
    5. End Sub


    Kann ich hier angeben, dass er diese Methode für ALLE NumericUpDowns durchläuft ohne, dass ich diese manuell angeben muss?
    @LassMichInRuhe So was:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Label1.Text = NumericUpDown1.Value.ToString
    3. Label2.Text = NumericUpDown1.Text
    4. End Sub
    sollte doch völlig genügen.
    Und:
    Dim mal das ByRef raus.
    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!
    Danke für deine Antwort, aber das löst ja nicht mein Problem. :P

    Ich erwarte zurzeit bei allen "NumericUpDowns.Value" einen Dezimalwert zurück.
    Jetzt geht ein Benutzer hin und löscht die ursprüngliche Eingabe ohne etwas neues einzutragen, klickt auf einen Button und ich rechne intern mit dem vorherigen Wert.

    Nach deinem Code müsste ich jetzt an jeder Stelle, an der ich zurzeit einen Dezimalwert habe, einen String nehmen und dann wieder zurück als Dezimalwert konvertieren...

    Ich finde das Verhalten schon sehr merkwürdig... Soll mir einen Dezimalwert zurückliefern und anstatt mir eine '0' zu geben wenn das Feld leer ist, gibt es mir einfach den vorherigen Wert.


    Das ByRef benötige ich aber, weil ich jetzt in Zukunft bei jedem Verlassen eines NUD eben dieses an die Methode übergebe, und prüfe ob etwas im Feld steht oder nicht und dann ggf. den Value-Wert auf 0 setze. Oder wie würdest du vorgehen?

    LassMichInRuhe schrieb:

    VB.NET-Quellcode

    1. ByRef
    Stell Dir diesen Code vor:

    VB.NET-Quellcode

    1. Public Overridable Function NumericUpDownExit(ByRef cNUD As System.Windows.Forms.NumericUpDown) As Integer
    2. cNUD = New NumericUpDown()
    3. Return 0
    4. End Function
    Mit ByRef kommt da ein neues Control mit initialen Properties zurück, mir ByVal nicht.
    Wohl aber kannst Du bei ByVal Properties des übergebenen Controls ändern.
    =====
    Probier es mal mit einer Extension:

    VB.NET-Quellcode

    1. Imports System.Runtime.CompilerServices
    2. Module Extensions
    3. <Extension()> _
    4. Public Function MyValue(ByVal nud As NumericUpDown) As Decimal
    5. If String.IsNullOrEmpty(nud.Text) Then
    6. Return 42 ' Der Wert, den Du zurück bekommen möxchtest
    7. End If
    8. Return nud.Value
    9. End Function
    10. End Module

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. Label1.Text = NumericUpDown1.Value.ToString
    4. Label2.Text = NumericUpDown1.Text
    5. Label3.Text = NumericUpDown1.MyValue.ToString
    6. End Sub
    7. End Class
    =============================
    Übrigens kommt nicht 0 zurück, sondern nud.Minimum.
    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!

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

    ByRef/ByVal
    Ich habe das mit dem ByVal gerade getestet und das funktioniert tatsächlich...
    Ich dachte ByVal legt nur eine Kopie des übergebenen Objektes an und Änderungen sind nur innerhalb der Methode gültig...

    Nach einem kurzen Herzinfarkt habe ich mir da eine kleine Testroutine gemacht und festgestellt, dass es sich wohl nur bei Controls so verhält und nicht bei allen Variablen...

    Trotzdem gefährlich, aber immerhin weiß ich es jetzt :S


    NumericUpDowns
    Das mit der Extension habe ich auch getestet -funktioniert auch, macht ja aber eigentlich nichts anderes als meine Methode ;)
    Ich habe allerdings mit Extensions noch nicht gearbeitet. Werde ich mir mal in den nächsten Tagen zu Gemüte führen.

    Kann ich damit die Standardmethode .Value für NumericUpDowns überschreiben?


    Wann kommt 0/nud.minimum zurück? Wenn ich in meine NUD eine 5 eintrage und auf einen Button zur Ausgabe klicke kommt 5 raus. Wenn ich danach in die NUD gehe und dann das Feld einfach leere (keine 0) und dann wieder auf den Button klicke, kommt immer noch 5 raus. Also kein nud.minimum ;)

    LassMichInRuhe schrieb:

    Kann ich damit die Standardmethode .Value für NumericUpDowns überschreiben?
    Nein.
    Dafür müsstest Du ein eigenes von NumericUpDown abgeleitetes Control schreiben, und dies in Deine GUI implementieren:

    VB.NET-Quellcode

    1. Public Class MyNumericUpDown
    2. Inherits NumericUpDown
    3. Public Overloads Property Value() As Decimal
    4. Get
    5. If String.IsNullOrEmpty(Me.Text) Then
    6. Return 42 ' Der Wert, den Du zurück bekommen möxchtest
    7. End If
    8. Return MyBase.Value
    9. End Get
    10. Set(value As Decimal)
    11. MyBase.Value = value
    12. End Set
    13. End Property
    14. 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!

    Reference-Type, Value-Type

    LassMichInRuhe schrieb:

    Ich dachte ByVal legt nur eine Kopie des übergebenen Objektes an und Änderungen sind nur innerhalb der Methode gültig...
    Dassis auch (fast!!) richtig
    ByVal legt nicht eine Kopie eines übergebenen Objekts ab. sondern eine Kopie des übergebenen Wertes. Bei einer Klasse (ReferenceType) ist dieser Wert ein Zeiger auf das Objekt. Der Zeiger ist (zwar) eine Kopie, aber er zeigt ja auf dasselbe Objekt! 8o
    Deshalb wirken Manipulationen an Class-Typen auf dasselbe Objekt, welches beim Aufrufer vorliegt.
    Dein Form bzw. MyNumericUpDown ist ein ReferenzTyp.
    Nach einem kurzen Herzinfarkt habe ich mir da eine kleine Testroutine gemacht und festgestellt, dass es sich wohl nur bei Controls so verhält und nicht bei allen Variablen...
    "nicht bei allen Variablen..." Bei Structures (ValueTypen) ist der Wert die Structure selber, also da stimmt deine Aussage sogar, dass das eine Kopie des Objekts übergeben wird.
    Mach dich schlau über die Unterschiede zw. Structure und Class, und sieh zu, dass du in Zukunft immer weist, ob du mit einer Structure arbeitest oder mit einer Class.

    Ganz kurz: Structures sind kleine und nicht weiter komplexe Objekte, alles annere sind Classes.