Wert in DataTable mit Helpers.dll - EditCurrent(of ...)

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

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

    Wert in DataTable mit Helpers.dll - EditCurrent(of ...)

    Hallo ihr lieben
    Ich nutze zum Ändern / Erstellen von Einträgen in meiner DataTable gerne die Helpers vom @ErfinderDesRades
    Hier ist es so, dass scheinbar eine Prüfung auf den korrekten Datentyp eingebaut ist.
    Wenn also in meiner DataTable eine Spalte als "Date" deklariert ist, so ist es nicht möglich hier z.B. "123" einzugeben.

    Die Form akzeptiert keine weiteren Eingaben, oder Button Klicks, solange ein Wert in einer Textbox vom falschen Format ist.
    Das ist prinzipiell wunderbar, weil ich mich dann nicht mit der Validierung der Eingaben rumärgern muss, es führt aber auch dazu, dass ein eingegebener Wert nicht gelöscht werden kann.

    Steht also schon ein Datum drinne, ist es nicht möglich dies zu löschen - weil ich hierdurch ja quasi einen ungültigen Datentyp erzeuge.
    Gibt es hierfür eine Lösung, oder hilft da nur etwas eigenes zu erstellen?
    @DerSmurf Der @ErfinderDesRades hat doch die Quellen seiner Helper-DLL hier veröffentlicht, such mal im Forum gezielt danach.
    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!

    DerSmurf schrieb:

    Steht also schon ein Datum drinne, ist es nicht möglich dies zu löschen - weil ich hierdurch ja quasi einen ungültigen Datentyp erzeuge.
    Was passiert denn, wenn du es versuchst?
    Und wie versuchst du es - per Code?
    Oder markierst du Zeichen in der Textbox, und drückst Entf?
    Oder per Backspace-Taste?
    Oder ists gar keine Textbox, sondern vielleicht eine Richtextbox?
    Oder noch was anneres - ein DatetimePicker?
    Ist in der Spalte überhaupt Null erlaubt? Weil wenn es das nicht ist, ist das Verhalten, dass du den Eintrag nicht löschen willst, ja zwingend notwendig.

    DerSmurf schrieb:

    Gibt es hierfür eine Lösung, oder hilft da nur etwas eigenes zu erstellen?


    Ich bin das umgangen, indem ich für die entsprechenden Felder jeweils ein Behavior gebaut habe - also ein Handling für z.B. Textbox, welches nur bestimmte Eingaben erlaubt.
    Ist evtl. nicht ganz das, wonach du suchst aber seitdem hab ich dein geschildertes Problem nicht mehr. Einfach beim Form_Load-Event die entsprechenden Textboxen registrieren.
    Findest du auch in meinem Planer-Projekt in den Helpers unter "ControlBehavior.vb"

    Hier mal ein Beispiel für eine "DateTextBox":



    Spoiler anzeigen

    Visual Basic-Quellcode

    1. #Region "DateTextBox"
    2. ''' <summary>
    3. ''' bewirkt, dass nur ein Datum in die Textboxen eingegeben werden kann - akzeptiert auch verkürzte Datum-Syntax:
    4. ''' "d", "dd", "dMM", "ddMM", und Space (darüber wird direkt das aktuelle Datum in die Textbox eingefügt)
    5. ''' Überprüft beim Verlassen der TextBox NICHT, ob die Eingabe korrekt war.
    6. ''' </summary>
    7. ''' <param name="dateTextBoxes"></param>
    8. Public Sub RegisterDateInputNoCheck(ParamArray dateTextBoxes As TextBox())
    9. For Each dtb In dateTextBoxes
    10. AddHandler dtb.Enter, AddressOf TextBox_Enter
    11. AddHandler dtb.KeyDown, AddressOf dtb_KeyDown
    12. AddHandler dtb.Leave, AddressOf dtb_Leave_noCheck
    13. Next
    14. End Sub
    15. ''' <summary>
    16. ''' bewirkt, dass nur ein Datum in die Textboxen eingegeben werden kann - akzeptiert auch verkürzte Datum-Syntax:
    17. ''' "d", "dd", "dMM", "ddMM", und Space (darüber wird direkt das aktuelle Datum in die Textbox eingefügt)
    18. ''' Überprüft beim Verlassen der Textbox auf korrekte Eingabe.
    19. ''' </summary>
    20. ''' <param name="dateTextBoxes"></param>
    21. Public Sub RegisterDateInput(ParamArray dateTextBoxes As TextBox())
    22. For Each dtb In dateTextBoxes
    23. AddHandler dtb.Enter, AddressOf TextBox_Enter
    24. AddHandler dtb.KeyDown, AddressOf dtb_KeyDown
    25. AddHandler dtb.Leave, AddressOf dtb_Leave
    26. Next
    27. End Sub
    28. ''' <summary>
    29. ''' hebt die Registrierung von "RegisterDateInput" wieder auf
    30. ''' </summary>
    31. ''' <param name="dateTextBoxes"></param>
    32. Public Sub unRegisterDateInput(ParamArray dateTextBoxes As TextBox())
    33. For Each dtb In dateTextBoxes
    34. RemoveHandler dtb.Enter, AddressOf TextBox_Enter
    35. RemoveHandler dtb.KeyDown, AddressOf dtb_KeyDown
    36. RemoveHandler dtb.Leave, AddressOf dtb_Leave
    37. Next
    38. End Sub
    39. Private Sub dtb_KeyDown(sender As Object, e As KeyEventArgs)
    40. Dim tb = DirectCast(sender, TextBox)
    41. Select Case e.KeyCode
    42. Case Keys.Space : tb.Text = Date.Today.ToShortDateString
    43. Case Keys.Enter : tb.SelectNextControl(tb, True, True, True, True)
    44. Case Keys.D0 To Keys.D9, Keys.NumPad0 To Keys.NumPad9, Keys.OemPeriod, Keys.Back 'nur Ziffern "." und Backspace zulassen
    45. Case Keys.Shift, Keys.Home, Keys.End, Keys.Delete, Keys.Left, Keys.Right
    46. Case Else : e.SuppressKeyPress = True 'alle anderen Eingaben ablehnen
    47. End Select
    48. End Sub
    49. Private Sub dtb_Leave_noCheck(sender As Object, e As EventArgs)
    50. Dim dateResult As Date
    51. Dim tb = DirectCast(sender, TextBox)
    52. If DateTryParseSpecial(tb.Text, dateResult) Then
    53. tb.Text = dateResult.ToShortDateString
    54. tb.ForeColor = SystemColors.WindowText
    55. End If
    56. End Sub
    57. Private Sub dtb_Leave(sender As Object, e As EventArgs)
    58. Dim dateResult As Date
    59. Dim tb = DirectCast(sender, TextBox)
    60. If DateTryParseSpecial(tb.Text, dateResult) Then
    61. tb.Text = dateResult.ToShortDateString
    62. tb.ForeColor = SystemColors.WindowText
    63. Else
    64. tb.Text = "ungültiges Datum"
    65. tb.ForeColor = Color.Red
    66. End If
    67. End Sub
    68. Private Function DateTryParseSpecial(txt As String, ByRef result As Date) As Boolean
    69. If Date.TryParse(txt, result) Then Return True
    70. Dim chars = txt.ToCharArray
    71. Dim tag = "", monat = Date.Today.Month.ToString, jahr = Date.Today.Year.ToString
    72. Select Case txt.Length
    73. Case 1 : tag = {chars(0)}
    74. Case 2 : tag = {chars(0), chars(1)}
    75. Case 3 : tag = {chars(0), chars(1)} : monat = {chars(2)}
    76. Case 4, 6, 8
    77. tag = {chars(0), chars(1)} : monat = {chars(2), chars(3)}
    78. If txt.Length > 4 Then jahr = txt.Substring(4)
    79. Case Else : Return False
    80. End Select
    81. Return Date.TryParse($"{tag}.{monat}.{jahr}", result)
    82. End Function
    83. #End Region 'DateTextBox
    84. #Region "SharedMethods"
    85. Private Sub TextBox_Enter(sender As Object, e As EventArgs)
    86. Dim tb = DirectCast(sender, TextBox)
    87. tb.SelectAll()
    88. End Sub
    89. Private Sub TextBox_numericKeyDown(sender As Object, e As KeyEventArgs)
    90. Dim tb = DirectCast(sender, TextBox)
    91. Select Case e.KeyCode
    92. Case Keys.Space : tb.Text = Date.Today.Year.ToString
    93. Case Keys.D0 To Keys.D9, Keys.NumPad0 To Keys.NumPad9, Keys.Back 'nur Ziffern und Backspace zulassen
    94. Case Keys.Shift, Keys.Home, Keys.End, Keys.Delete, Keys.Left, Keys.Right
    95. Case Else : e.SuppressKeyPress = True 'alle anderen Eingaben ablehnen
    96. End Select
    97. End Sub
    98. #End Region 'SharedMethods
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    RodFromGermany schrieb:

    Der @ErfinderDesRades hat doch die Quellen seiner Helper-DLL hier veröffentlicht, such mal im Forum gezielt danach.

    Ja. Weil ich den Code aber nur so halbwegs verstehe, mag ich da nur ungerne drin rumfurwerken.

    @ErfinderDesRades
    Ich habe wie in deiner Anleitung beschrieben eine Form erstellt, welche die Daten in Textboxen anzeigen.
    Dort versuche ich innerhalb der Form das Datum zu löschen - also den Inhalt der Textbox zu entfernen.
    Hierbei ist es egal, ob ich dies mit Backspace, oder Entf Taste, oder einzelne Zeichen, oder den gesamte Inhalt lösche.
    Sobald ich das gültige Datum entfernt habe, kann ich die Textbox nicht verlassen - also keine andere TB anwählen, oder die Buttons mit DialogResult OK oder Cancel bedienen.
    Erst wenn, die TB wieder ein gültiges Datum enthält gehts weiter.
    So ist also das löschen unmöglich.

    DerSmurf schrieb:

    mag ich da nur ungerne drin rumfurwerken.
    Das ist ein gigantisches Lern-Potenzial.
    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!

    DerSmurf schrieb:

    So ist also das löschen unmöglich.


    Wenn das DataSet Datum verlangt, kannste das nicht einfach leer lassen. Dann musste mit Pseudo-Datum arbeiten (z.B. 01.01.1900) und lässt dir das im DataGridView oder wo auch
    immer ausblenden, wenn es dem Wert entspricht. Mach ich bei meiner Anwendung z.B. so.

    Anders wäre der Datensatz ja nicht komplett, wenn du statt dem geforderten Date ein "" drin stehn hast ;)
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Ich habs jetzt beforscht - stimmt: An Nullable-Date-Spalten gebundene Textboxen verhalten sich bescheuert.
    Das hat aber mit den Dataset-Extensions nix zu tun.
    Die Lösung besteht darin, dem Binding ein NullValue mitzuteilen - also einen Wert, den die BindingSource als <DbNull> übersetzt, wenn sie die Eingabe in die DataSource übernimmt.
    Idiotischerweise kann man im Designer in den (Advanced) Databinding-Einstellungen eigentlich solche NullValues festlegen - aber grad bei Textboxen kann man im Designer grad '' nicht als NullValue festlegen.
    Anderes kann man als NullValue festlegen, aber grad '' wird nicht angenommen :thumbdown: .
    Das muss man dann codeseitig machen.

    Habe dazu NullableDateTimePicker um ein weiteres CodeSample erweitert, wo's auch nochmal genauer erklärt ist.
    Auch um Reklame zu machen für mein NullableDateTimePicker. Weil Textboxen zur Datum-Eingabe zu nutzen ist recht fragwürdig.
    Bzw. es ist höchst schwierig, eine Datum-Textbox wasserdicht zu implementieren.

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