Der DateTimePicker kann leider keinen Nullwert im Value-Wert darstellen und an die Datenbank zurückspeichern. Das habe ich wie folgt gelöst:
Voraussetzungen für den Code:
1. Eine Windows-Form foDatum öffnen und im Designer einen MonthCalendar platzieren. Der folgenden Code in die Form einkopieren:
2. Ein DataGridView ist initialisiert und mit einer DB-Connection verbunden. Das könnte in etwa so aussehen (es sind nicht alle Variablen definiert):
Beim Click auf eine Zeile des DataGridView wird das DataRowView drvRes initialisiert und mit Daten gefüllt. Diese Daten werden anschliessend in Textfeldern bearbeitet und jeweils per Code zurückgeschrieben, wie das Beispiel unten zeigt. Auf diese Weise habe ich die volle Kontrolle, was wie in die DB zurückgeschrieben wird.
Der Aufruf erfolgt auf diese Weise:
Schlusskommentar: Vermutlich wäre vieles einfacher möglich. Ich bin mit diesem Weg durchaus zufrieden
Voraussetzungen für den Code:
1. Eine Windows-Form foDatum öffnen und im Designer einen MonthCalendar platzieren. Der folgenden Code in die Form einkopieren:
VB.NET-Quellcode
- Public Class foDatum
- Private Sub foDatum_Load(sender As Object, e As EventArgs) Handles MyBase.Load
- ' Die Varabeln Left und Top müssen vorher als Public-Variabeln geschrieben werden. Left und Top kann nicht im Form_Load beschrieben und gerechnet werden, wenn die Form mit form.ShowDialog() geöffnet wird
- Me.Left = vfoDatumLeft
- Me.Top = vfoDatumTop
- Me.Width = 237
- Me.Height = 201
- End Sub
- Private Sub MonthCalendar1_DateSelected(sender As Object, e As DateRangeEventArgs) Handles MonthCalendar1.DateSelected
- vDatumsWahl = e.Start.ToShortDateString()
- Me.Close()
- End Sub
- Private Sub MonthCalendar1_KeyDown(sender As Object, e As KeyEventArgs) Handles MonthCalendar1.KeyDown
- If e.KeyCode = Keys.Escape Then
- vDatumsWahl = Nothing
- Me.Close()
- End If
- End Sub
- End Class
2. Ein DataGridView ist initialisiert und mit einer DB-Connection verbunden. Das könnte in etwa so aussehen (es sind nicht alle Variablen definiert):
VB.NET-Quellcode
-
- Public dbConn As New OleDbConnection
- Public daRes As New OleDbDataAdapter
- Public dvRes As New DataView
- Public dtRes As New DataTable
- Public dsRes As New DataSet
- Public bsRes As New BindingSource
- Public drvRes As DataRowView = Nothing
- dbConn.ConnectionString = "PROVIDER=Microsoft.ACE.OLEDB.12.0; Data Source=" + ACCESS-Datenbank-Pfad und Name
- dbConn.Open()
- daRes = New OleDbDataAdapter("SELECT " & sqlSelect & " FROM " & sqlFrom & " WHERE " & sqlWhere & " ORDER BY " & sqlOrder, dbConn)
- Dim cbRes As New OleDbCommandBuilder(daRes)
- dtRes = New DataTable("Ressourcen")
- daRes.Fill(dtRes)
- dbConn.Close()
- Dim bsRes As New BindingSource
- dvRes = New DataView(dtRes)
- bsRes.DataSource = dvRes
- DataGridView.DataSource = bsRes
Beim Click auf eine Zeile des DataGridView wird das DataRowView drvRes initialisiert und mit Daten gefüllt. Diese Daten werden anschliessend in Textfeldern bearbeitet und jeweils per Code zurückgeschrieben, wie das Beispiel unten zeigt. Auf diese Weise habe ich die volle Kontrolle, was wie in die DB zurückgeschrieben wird.
Der Aufruf erfolgt auf diese Weise:
VB.NET-Quellcode
-
- Private Sub btResDatum_Click(sender As Object, e As EventArgs) Handles btResDatum.Click ' ein Button sonstwo in der Form
- teResDatum.Text = DatumsWahl(Me.Left + 95, Me.Top + 500) ' teResDatum.text ist das Textfeld, in welches das Datum zurückgeschrieben wird, die Positionen Left & Top werden mitgegeben, damit der DatePicker am richtigen Ort erscheint. Leider sind zusätzliche Anpassungen unumgänglich
- If vNeuRB = False Then ' hier wird geprüft, ob ein neuer Datensatz in der Datenbank geschrieben oder ein aktueller Datensatz verändert werden soll, die vNeuRB-Variable wird gesetzt, wenn ein neuer Datensatz geschrieben werden soll
- drvRes.BeginEdit()
- If IsDate(teResDatum.Text) = False Then
- drvRes("Datum") = DBNull.Value ' Damit wird der Nullwert an die Datenbank-Zwischenspeicherung übergeben
- teResDatum.Text = "__.__.____" ' Das Masken-Textfeld muss wieder zurückgeschrieben werden auf die
- Else
- drvRes("Datum") = teResDatum.Text ' Hier wird der gewählte Datumswert übergeben
- End If
- drvRes("WriteDate") = Now() ' Hier wird das aktuelle Änderungsdatum für den Datensatz übergeben
- drvRes.EndEdit()
- Call ResChangeFields() ' Aufruf der definitiven Speicherung in die Datenbank
- teResDatum.SelectAll() ' Das Datum wird markiert, falls etwas von Hand geändert werden soll
- End If
- End Sub
- Public Function DatumsWahl(ByVal xPos As Integer, ByVal yPos As Integer)
- vfoDatumLeft = xPos
- vfoDatumTop = yPos
- foDatum.ShowDialog()
- DatumsWahl = vDatumsWahl
- End Function
- Public Sub ResChangeFields()
- Dim dt1Res As DataTable = dtRes.GetChanges()
- If dt1Res IsNot Nothing Then
- Try
- If dbConn.State = ConnectionState.Closed Then dbConn.Open()
- daRes.Update(dt1Res)
- dtRes.AcceptChanges()
- If dbConn.State = ConnectionState.Open Then dbConn.Close()
- Catch ex As System.Exception
- MessageBox.Show(ex.Message, "Speichern fehlgeschlagen!", MessageBoxButtons.OK, MessageBoxIcon.Information)
- dtRes.RejectChanges()
- If dbConn.State = ConnectionState.Open Then dbConn.Close()
- End Try
- End If
- End Sub
Schlusskommentar: Vermutlich wäre vieles einfacher möglich. Ich bin mit diesem Weg durchaus zufrieden