0

I've read various workarounds on this, but cannot get any working well. I have a large number of Datetimepickers on a form, all bound to datatables via a BindingSource. Problem being, a lot of the data holds null values for dates, but these display as datetime.now. I want some indication that these are null, not an actual date.

As it happens, I have a 'themer' that iterates through all controls on the form. I add a handler to each on ValueChanged:

      ElseIf TypeOf ct Is DateTimePicker Then

            Dim dtp = DirectCast(ct, DateTimePicker)
            With dtp
                AddHandler dtp.ValueChanged, AddressOf Zzapper.Dtp_ValueChanged
            End With

Handler:

Public Sub Dtp_ValueChanged(ByVal sender As Object, ByVal e As EventArgs)
    Dim dtp As DateTimePicker = DirectCast(sender, DateTimePicker)
    Dim result As DateTime

    If DateTime.TryParse(dtp.Value, result) Then
        dtp.Format = DateTimePickerFormat.Long
    Else
        dtp.CustomFormat = " "
        dtp.Format = DateTimePickerFormat.Custom
    End If

However, this does not get fired on null values (discerned via breakpoints and counting how often it gets called - only gets called for non-null values), I'm guessing because technically the value doesn't change in the control itself.

Can anyone else think of a solution?

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
stigzler
  • 793
  • 2
  • 12
  • 29
  • What exactly do you think this would acheive: `DateTime.TryParse(dtp.Value, result)`. The point of `TryParse` is to try to parse a `String` as a `DateTime`. You already have a `DateTime` though, so what's the point? The `Value` property is type `DateTime` so it is ALWAYS a `DateTime`. That's exactly the problem with that control and nullable data. What you ought to do is create your own derived control with a nullable property and bind to that instead, then get and set the `Value` property inside that. – jmcilhinney May 30 '21 at 02:11
  • I thought it would fail if the date is dbnull. I'm guessing the control just doesn't change the date at all if it is passed a dbnull as the .ValueChanged event isn't even fired. – stigzler May 30 '21 at 07:31
  • But even if the event was raised, the Value property is still type DateTime, so it would still have to succeed. That property can't be anything but a valid DateTime value. If anything failed or would be in the Binding. – jmcilhinney May 30 '21 at 08:28
  • @stigzler Perhaps [How can I make a DateTimePicker display an empty string?](https://stackoverflow.com/q/846395/1115360) will lead you to a solution. – Andrew Morton May 30 '21 at 08:42
  • @AndrewMorton - thanks - indeed, that's where the code in my original post came from! – stigzler Jun 01 '21 at 08:51

1 Answers1

1

I created a DataTable. I presume yours came from a database. In the DefaultForNull method I just looped through the columns I needed to check and inserted a default value for the missing dates.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim dt As New DataTable
    dt.Columns.Add("Date1", GetType(Date))
    dt.Columns.Add("Date2", GetType(Date))
    dt.Columns.Add("Date3", GetType(Date))
    dt.Rows.Add({#3/19/2021#, DBNull.Value, #3/20/2020#})
    dt.Rows.Add({DBNull.Value, #7/12/2020#, #8/4/2021#})
    DefaultForNullDates(dt, #1/1/1900#)
    For Each row As DataRow In dt.Rows
        Debug.Print($"{row(0).ToString}, {row(1).ToString}, {row(2).ToString}")
    Next
End Sub

Private Sub DefaultForNullDates(dt As DataTable, DefaultDate As Date)
    Dim lst As New List(Of String) From {"Date1", "Date2", "Date3"}
    For Each ColName In lst
        For Each row As DataRow In dt.Rows
            If row(ColName) Is DBNull.Value Then
                row(ColName) = DefaultDate
            End If
        Next
    Next
End Sub

Depending on your database you can probably do this directly in you select query.

Mary
  • 14,926
  • 3
  • 18
  • 27