How to alter a .NET DateTimePicker control to allow enter null values?
Asked Answered
F

7

24

What's the easiest and most robust way of altering the .NET DateTimePicker control, to allow users to enter null values?

Fruitage answered 12/11, 2008 at 15:48 Comment(1)
Another option is to use a MaskedTextBox with a mask of 00/00/0000. This allows somewhat intuitive data entry and probably the most intuitive UX for backing out a date field.Tabbatha
K
6

Here's an approach from this CodeProject article on creating a Nullable DateTimePicker.

I have overridden the Value property to accept Null value as DateTime.MinValue, while maintaining the validation of MinValue and MaxValue of the standard control.

Here's a version of the custom class component from the article

public class NullableDateTimePicker : System.Windows.Forms.DateTimePicker
{
    private DateTimePickerFormat originalFormat = DateTimePickerFormat.Short;
    private string originalCustomFormat;
    private bool isNull;

    public new DateTime Value
    {
        get => isNull ? DateTime.MinValue : base.Value;
        set
        {
            // incoming value is set to min date
            if (value == DateTime.MinValue)
            {
                // if set to min and not previously null, preserve original formatting
                if (!isNull)
                {
                    originalFormat = this.Format;
                    originalCustomFormat = this.CustomFormat;
                    isNull = true;
                }

                this.Format = DateTimePickerFormat.Custom;
                this.CustomFormat = " ";
            }
            else // incoming value is real date
            {
                // if set to real date and previously null, restore original formatting
                if (isNull)
                {
                    this.Format = originalFormat;
                    this.CustomFormat = originalCustomFormat;
                    isNull = false;
                }

                base.Value = value;
            }
        }
    }

    protected override void OnCloseUp(EventArgs eventargs)
    {
        // on keyboard close, restore format
        if (Control.MouseButtons == MouseButtons.None)
        {
            if (isNull)
            {
                this.Format = originalFormat;
                this.CustomFormat = originalCustomFormat;
                isNull = false;
            }
        }
        base.OnCloseUp(eventargs);
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);

        // on delete key press, set to min value (null)
        if (e.KeyCode == Keys.Delete)
        {
            this.Value = DateTime.MinValue;
        }
    }
}
Killjoy answered 12/11, 2008 at 15:56 Comment(3)
Yes Mr Grazoli's NullableDateTimePicker does do the job although I think that someone should review it and try and get rid of those ugly WndProc callsMacrobiotics
The other thing about the code is that it didn't seem to do what it was supposed to do. I don't know, maybe I was doing something wrong. Don't have a lot of time to spend messing around with it. Using the DTPs ShowCheckBox idea seems more promising really.Ingrid
While the solution allows the user to clear out a date, you can no longer set focus to the control or use the keyboard to re-enter a non null date. One step fwd, two back.Cockerel
U
47

You don't need to modify it to do this.

The DateTimePicker in .net actually has a checkbox built-in.

Set the ShowCheckBox property to true.

Then you can use the Checked property to see if the user has entered a value.

http://msdn.microsoft.com/en-us/library/system.windows.forms.datetimepicker.showcheckbox(VS.80).aspx

Ulm answered 19/11, 2009 at 12:32 Comment(1)
The checkbox implementation is all kinds of fail though. Doesn't trigger events properly.Airfoil
K
6

Here's an approach from this CodeProject article on creating a Nullable DateTimePicker.

I have overridden the Value property to accept Null value as DateTime.MinValue, while maintaining the validation of MinValue and MaxValue of the standard control.

Here's a version of the custom class component from the article

public class NullableDateTimePicker : System.Windows.Forms.DateTimePicker
{
    private DateTimePickerFormat originalFormat = DateTimePickerFormat.Short;
    private string originalCustomFormat;
    private bool isNull;

    public new DateTime Value
    {
        get => isNull ? DateTime.MinValue : base.Value;
        set
        {
            // incoming value is set to min date
            if (value == DateTime.MinValue)
            {
                // if set to min and not previously null, preserve original formatting
                if (!isNull)
                {
                    originalFormat = this.Format;
                    originalCustomFormat = this.CustomFormat;
                    isNull = true;
                }

                this.Format = DateTimePickerFormat.Custom;
                this.CustomFormat = " ";
            }
            else // incoming value is real date
            {
                // if set to real date and previously null, restore original formatting
                if (isNull)
                {
                    this.Format = originalFormat;
                    this.CustomFormat = originalCustomFormat;
                    isNull = false;
                }

                base.Value = value;
            }
        }
    }

    protected override void OnCloseUp(EventArgs eventargs)
    {
        // on keyboard close, restore format
        if (Control.MouseButtons == MouseButtons.None)
        {
            if (isNull)
            {
                this.Format = originalFormat;
                this.CustomFormat = originalCustomFormat;
                isNull = false;
            }
        }
        base.OnCloseUp(eventargs);
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);

        // on delete key press, set to min value (null)
        if (e.KeyCode == Keys.Delete)
        {
            this.Value = DateTime.MinValue;
        }
    }
}
Killjoy answered 12/11, 2008 at 15:56 Comment(3)
Yes Mr Grazoli's NullableDateTimePicker does do the job although I think that someone should review it and try and get rid of those ugly WndProc callsMacrobiotics
The other thing about the code is that it didn't seem to do what it was supposed to do. I don't know, maybe I was doing something wrong. Don't have a lot of time to spend messing around with it. Using the DTPs ShowCheckBox idea seems more promising really.Ingrid
While the solution allows the user to clear out a date, you can no longer set focus to the control or use the keyboard to re-enter a non null date. One step fwd, two back.Cockerel
S
4

Placing an additional checkbox labeled something like "enable notification" that enables / disables the DateTimePicker.

Suitor answered 12/11, 2008 at 15:50 Comment(0)
S
2

Tri's solution did not quite cut it for me and so thought Mr. Grazioli and he did something about it: http://www.codeguru.com/csharp/csharp/cs_controls/custom/article.php/c9645

Sliest answered 9/12, 2008 at 13:54 Comment(0)
R
1

Set the ShowCheckBox property to true.

Then you can use the Checked property as follows:

private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
    DateTimePicker thisDateTimePicker = (DateTimePicker)sender;
    if (thisDateTimePicker.Checked == false)
    {
        thisDateTimePicker.CustomFormat = @" "; //space
        thisDateTimePicker.Format = DateTimePickerFormat.Custom;
    }
    else
    {
        thisDateTimePicker.Format = DateTimePickerFormat.Short;
    }
}
Rodney answered 9/10, 2015 at 6:26 Comment(1)
from all proposed solutions this was the easiest, shortest and ui friendlyElatia
E
0

I posted my long way around solution, which has some findings in the code comments about the peculiar issues with this control:

DateTime Picker null value

Evora answered 23/12, 2011 at 11:33 Comment(0)
U
0

Replacing the original code from the CodeProject article mentioned with this one allows to "enable" the keyboard and focus set again:

protected override void OnKeyDown(KeyEventArgs e)
{
    base.OnKeyDown (e);

    if (e.KeyCode == Keys.Delete)
    {
        this.Value = DateTime.MinValue;
    } 
    else
    {
        if (this.Value == DateTime.MinValue)
        {
            this.Value = DateTime.Now;
            this.Format = oldFormat;
            this.CustomFormat = oldCustomFormat;
            bIsNull = false;
        }
    }
}
Understudy answered 13/6 at 8:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.