Der klassische DateTimepicker hat zwar eine Checkbox, mit der man ausdrücken kann, dass sein Wert nicht gilt, aber leider enthält er immer trotzdem einen Wert in seiner .Value-Property.
Hier habe ich ihn ein bischen modifiziert, nämlich seine Property Value As DateTime abschattiert mit einer neuen Property Value As Nullable(Of DateTime) (alias 'DateTime?').
Somit kann man dem DateTimepicker als Value auch Nothing zuweisen, und er uncheckt daraufhin seine Checkbox.
Insbesondere inne Datenbänkerei ist das wichtig, wenn man für ein Datum-Feld auch Nullwerte zulassen will (etwa ein Geburtsdatum ohne Angabe), und daher habe ich darauf geguckt, dass die neue Value-Property auch DataBindable ist.
Hier der Weltbewegende Code:
VB.NET-Quellcode
- Imports System.ComponentModel
- <DesignerCategory("Code")> _
- Public Class NullableDateTimePicker : Inherits DateTimePicker
- <Bindable(True)> _
- Public Shadows Property Value As Date?
- Get
- If Not Checked Then Return Nothing
- Return MyBase.Value
- End Get
- Set(ByVal value As Date?)
- If value.Equals(Me.Value) Then Return
- Checked = value.HasValue
- If value.HasValue Then MyBase.Value = value.Value
- End Set
- End Property
- End Class
Der Code ist eiglich überaus trivial, allerdings, um ihn zu verstehen, muß man ühaupt das Problem, und dann das Konzept der Nullable(Of T) - Struktur verstehen, welche als Lösung angewandt wird.
Das Problem: Strukturen und Klassen
DateTime ist eine Struktur (Wert-Typ), keine Klasse (Referenz-Typ). Referenz-Typ-Variablen enthalten nicht ihren Wert, sondern sind im Grunde Zeiger auf eine Speicherstelle, wo der eigentliche Wert liegt. Daher kann man diese Zeiger auf Null setzen, und dann zeigen sie halt auf Nichts - Nothing.
Wert-Typ-Variablen hingegen zeigen nicht auf eine Speicherstelle, wo der Wert ist - stattdessen enthalten sie den Wert selbst.
Weist man also einem String (Referenz-Typ) Nothing zu, so ist die Variable Nothing - kein String.
Weist man dagegen einem Point (Wert-Typ) Nothing zu, so nimmt die Variable nicht den "Wert" Nothing an, sondern enthält immer noch einen gültigen Point, nämlich (0, 0).
So gehts auch einem DateTime - wenn man dem Nothing zuweist, enthält er immer noch ein gültiges Datum, nämlich #1/1/0001#.
Wie gesagt: Besonders inne Datenbänkerei braucht man es aber mitunter, die Tatsache abspeichern zu können, dass ein Wert eben nicht gesetzt ist.
Jo, und mittm klassischen DateTimePicker kann man diese Angabe einfach nicht eingeben, denn dessen Value-Property ist vom Type DateTime, und kann den "Wert" Nothing überhaupt nicht annehmen.
Die Nullable(Of T) - Structure
Das ist ein bischen die Quadratur des Kreises, nämlich eine Structure, die eben doch den "Wert" Nothing annehmen kann.
Sie enthält 2 Properties: einmal den eigentlichen Wert, und zum anderen die Information, ob sie ühaupt einen Wert hat.
Jo, was man damit anstellen kann, ist hier ja gezeigt, und im Sample-Projekt ist auch gezeigt, wie das mittm typisierten Dataset zusammenarbeitet (und dadurch auch mit ggfs. hinterlegten Datenbanken).
Denn wenn man eine Dataset-Datenspalte mit AllowNull = True anlegt, so erscheint die entsprechende Property nicht als T, sondern als Nullable(Of T), und die DataAdapter sorgen dann dafür, dass - im Falle von nicht gesetzt - der DbNull-Wert in die Datenbank gespeichert wird.
Hier noch eine weitere SampleSolution: DateBingingTester
Da experimentiere ich auch mit Textboxen, an NullableDate gebunden herum - aus dem ErklärText:
Erklärbär schrieb:
"In (Advanced)-Databinding-Einstellungen kann man ein Nullvalue einstellen.
Idiotischerweise kann man bei TextBoxen im Designer nicht''
(Leerstring) als NullValue einstellen.
Das führt zum paradoxen Verhalten, dass eine Textbox bei einem Null-Datum leer ist - wenn man aber ein Datum einmal eingegeben hat, kann man es nicht mehr rauslöschen.
Lösung: Man muss codeseitig das Binding setzen, und dabei als NullValue''
angeben.
Wiedemauchsei.
Eine Textbox als Eingabe für Datumse ist eh höchst fragwürdig - sowas wasserdicht zu coden ist sehr anspruchsvoll.
Ich empfehle stattdessen meinen NullableDateTimePicker, geerbt von DateTimepicker.
Der Standard-DateTimepicker, gebunden an ein Nullable-Date baut Mist.
Bei DateTimepicker sind aber auch Min- und Max-Date zu beachten. Ein Datum, was aus diesem Bereich herausfällt verursacht unerwartetes Verhalten.
Das wiederum erzwingt im Dataset sehr ungewöhnliche DefaultValues festzulegen - hier: 1.1.1753
Damit generierte Datensätze (zB per bs.AddNew) im DTP sinnvoll darstellbar sind."
Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()