DateTimePicker and DBNull


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> color=teal>You can’t bind a Windows Forms DateTimePicker to a field
that might contain DBNull… so I did this;


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-tab-count: 1">      style="COLOR: blue">public class
DBDateTimePicker:DateTimePicker


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-tab-count: 1">     
{


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> 


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-tab-count: 2">           
public
DBDateTimePicker()


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-tab-count: 2">           
{


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-tab-count: 3">                 
//


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-tab-count: 3">                 
// TODO: Add constructor logic
here


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-tab-count: 3">                 
//


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-tab-count: 2">           
}


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> 


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">       
public style="COLOR: blue">object DBValue


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">       
{


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">           
get


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">           
{


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">               
if ( style="COLOR: blue">this.Checked)


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">                   
return style="COLOR: blue">base.Value;


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">               
else


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">                   
return
System.DBNull.Value;


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">           
}


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">           
set


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">           
{


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">               
if (System.Convert.IsDBNull( style="COLOR: blue">value))


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">    style="mso-spacerun: yes">                 style="COLOR: blue">this.Checked= style="COLOR: blue">false;


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">               
else


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">                   
this.Value = Convert.ToDateTime( style="COLOR: blue">value);


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">           
}


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-spacerun: yes">       
}


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"> style="mso-tab-count: 1">     
}


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> color=teal>Then I bind to “DBValue”  (instead of Value) and it appears to
work fine… if it is null, it is unchecked and disabled, otherwise it is enabled
and can be set to any normal date value… if you uncheck the box yourself, then
the data field is set to DBNull…


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> color=teal> 


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> color=teal>Not sure if it the best idea, but I can’t override Value so this
seems like a reasonable alternative… of course, I never looked around for the
“official” solution or any other possible answers, so let me know if you have a
better idea!


Comments (8)

  1. Anonymous says:

    Another little code snippet : Code/Tea/Etc…

  2. Eto says:

    This is what I found as well.. but I got into a pickle, because for some unknown reason, binding to this ALWAYS makes it flag the DataRow as modified, so using HasChanges() will ALWAYS return true!.. I wanted to know if the user changed anything so I can prompt them about saving before exiting, so I found this variation to work (FINALLY!):

    public class DbDateTimePicker : System.Windows.Forms.DateTimePicker

    {

    public DbDateTimePicker()

    {

    }

    [Bindable(true), Browsable(false)]

    public new object Value

    {

    get

    {

    if (Checked) return base.Value;

    else return DBNull.Value;

    }

    set

    {

    if (Convert.IsDBNull(value)) this.Checked = false;

    else base.Value = Convert.ToDateTime(value);

    }

    }

    }

  3. Kevin says:

    both of your solution dont’ seem to work for me. the db value did get binded, but won’t unchecked when value is dbnull.

  4. Kevin says:

    I think I found a perfect solution to it.

    even with the modification with Eto, the picker still have problem, because the picker won’t update itself when changing from unchecked to checked or vice versa, with little magic touch it will work.

    public class DbDateTimePicker : System.Windows.Forms.DateTimePicker

    {

    public DbDateTimePicker()

    {

    }

    [Bindable(true), Browsable(false)]

    public new object Value

    {

    get

    {

    if (Checked) return base.Value;

    else return DBNull.Value;

    }

    set

    {

    if (Convert.IsDBNull(value))

    {

    //the line below is the magic touch

    this.Checked = true;

    this.Checked = false;

    }

    else base.Value = Convert.ToDateTime(value);

    }

    }

    }

    it seems that the picker UI won’t update unless it clearly change from Checked true to false.

  5. Thanks Kevin, I’ll have to try that… it is odd that it was necessary though, since I am using that control without any issues in my applications already. Perhaps there is some other difference in how I am binding and handling changes that avoids this problem?

  6. Alton Goerby says:

    Just bind to DateTimePicker.Text and it will work; If DBNull is autoconverted to DateTime.Now;

    😉

  7. Hugoski says:

    The same solution of Kevin, but in Visual Basic .NET.

    Option Explicit On

    Imports System

    Imports System.ComponentModel

    Public Class DBDateTimePicker

    Inherits System.Windows.Forms.DateTimePicker

    #Region " Windows Form Designer generated code "

    Public Sub New()

    MyBase.New()

    ‘This call is required by the Windows Form Designer.

    InitializeComponent()

    ‘Add any initialization after the InitializeComponent() call

    End Sub

    ‘UserControl overrides dispose to clean up the component list.

    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

    If disposing Then

    If Not (components Is Nothing) Then

    components.Dispose()

    End If

    End If

    MyBase.Dispose(disposing)

    End Sub

    ‘Required by the Windows Form Designer

    Private components As System.ComponentModel.IContainer

    ‘NOTE: The following procedure is required by the Windows Form Designer

    ‘It can be modified using the Windows Form Designer.

    ‘Do not modify it using the code editor.

    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

    components = New System.ComponentModel.Container

    End Sub

    #End Region

    <Bindable(True), Browsable(True)> _

    Public Shadows Property Value() As Object

    Get

    If (MyBase.Checked) Then

    Return MyBase.Value

    Else

    Return DBNull.Value

    End If

    End Get

    Set(ByVal Value As Object)

    If IsDBNull(Value) Then

    Me.Checked = True

    Me.Checked = False

    Else

    MyBase.Value = Convert.ToDateTime(Value)

    End If

    End Set

    End Property

    End Class

  8. Magnus Aycox says:

    The above solution just doesn’t cut it in all situations. The checkbox doesn’t respond correctly when going from a DBNull row to a non-DBNull row. Please find below the fixed code.

    public class DBDateTimePicker : System.Windows.Forms.DateTimePicker

    {

    public DBDateTimePicker()

    {

    }

    [Bindable(true), Browsable(false)]

    public new object Value

    {

    get

    {

    if(Checked)

    return(base.Value);

    else

    return(DBNull.Value);

    }

    set

    {

    if(System.Convert.IsDBNull(value))

    {

    base.Value = DateTime.Today; // Show todays date as default when greyed out

    //the line below is the magic touch

    this.Checked = true;

    this.Checked = false;

    }

    else

    {

    this.Checked = true; // Set checked – just setting the Value property isn’t enough

    base.Value = Convert.ToDateTime(value);

    }

    }

    }

    }