如何在未选择日期时设置具有空值的DateTimePicker(C# WinForms)

18
Binding b = new Binding( "Value", person, "BdayNullable", true );
dtBirthdayNullable.DataBindings.Add( b );
b.Format += new ConvertEventHandler( dtBirthdayNullable_Format );

b.Parse += new ConvertEventHandler( dtBirthdayNullable_Parse );

void dtBirthdayNullable_Format( object sender, ConvertEventArgs e )
{
    // e.Value is the object value, we format it to be what we want to show up in the control

    Binding b = sender as Binding;
    if ( b != null )
    {
        DateTimePicker dtp = (b.Control as DateTimePicker);
        if ( dtp != null )
        {
            if ( e.Value == DBvalue.value )
            {
                dtp.ShowCheckBox = true;
                dtp.Checked = false;

                // have to set e.Value to SOMETHING, since it's coming in as NULL
                // if i set to DateTime.Today, and that's DIFFERENT than the control's current 
                // value, then it triggers a CHANGE to the value, which CHECKS the box (not ok)
                // the trick - set e.Value to whatever value the control currently has.  
                // This does NOT cause a CHANGE, and the checkbox stays OFF.
                e.Value = dtp.Value;    
            }
            else
            {
                dtp.ShowCheckBox = true;
                dtp.Checked = true;
                // leave e.Value unchanged - it's not null, so the DTP is fine with it.
            }
        }
    }
}
void dtBirthdayNullable_Parse( object sender, ConvertEventArgs e )
{
    // e.value is the formatted value coming from the control.  
    // we change it to be the value we want to stuff in the object.

    Binding b = sender as Binding;
    if ( b != null )
    {
        DateTimePicker dtp = (b.Control as DateTimePicker);
        if ( dtp != null )
        {
            if ( dtp.Checked == false )
            {
                dtp.ShowCheckBox = true;
                dtp.Checked = false;
                e.Value = DBvalue.Value
            }
            else
            {
                DateTime val = Convert.ToDateTime( e.Value );
                e.Value =val;
            }
        }
    }
}

编辑

我在这里找到了一个好的解决方案:

http://blogs.interknowlogy.com/danhanan/archive/2007/01/21/10847.aspx

还有另一个完美的解决方案:

http://www.mofeel.net/70-microsoft-public-dotnet-framework-windowsforms/8806.aspx


我知道这是一个老问题,但你应该考虑将这两个链接发布为答案。它们完美地解决了需要将可空数据库字段绑定到DateTimePicker的问题。 - edsobo
2
可能是DateTimePicker Null Value (.NET)的重复问题。 - bluish
第一个链接对我很有帮助。 - Mario Vázquez
6个回答

28

DateTimePicker 无法设置为 null,因为 DateTime 无法为 null,但您可以将其设置为 DateTime.MinValue,这是未初始化的 DateTime 的默认值。然后,您只需检查 dtp.Value = DateTime.MinValue,如果是,则将其视为 null。

但是,如果您想要真正区分何时未选择任何值,最简单的方法是将 DateTimePicker.ShowCheckBox 设置为 true,然后检查 dtp.Checked,如果为 true,则读取该值,否则将其视为 null。


是的,这是一些可能会让你措手不及的东西。幸运的是(或不幸的是<g>),有很多第三方可空日期选择器控件可供使用 - http://www.google.com/search?q=nullable+datetimepicker - Dan F
对于那些通过搜索WPF日期选择器类似问题而来到这个问题的人:使用可空的DateTime(DateTime?)作为绑定源来解决此问题。 - Breeze

18

如果您的绑定源提供了“null日期”或您不想显示的日期值,您可以检查一下。

如果是这样,请选择自定义格式:

yourDTP.Format = DateTimePickerFormat.Custom
yourDTP.CustomFormat = " "
在用户操作时,添加“CloseUp”或“ValueChanged”事件处理程序以重置格式:
yourDTP.Format = DateTimePickerFormat.Short

2
这是最简单和最优雅的解决方案。应该被接受的答案。 - Vishnoo Rath
正如@VishnooRath所指出的那样,这是唯一能传达我们想向用户展示的真实含义的解决方案:根本没有值;用户不关心它是否为null或datetime.min结构值或其他任何东西... - Marcelo Scofano Diniz
如果用户想要清除该值(将其重新设置为null),该怎么办? - kgzdev

2
这是我的解决方案。由于我不能使用NULLS,所以我将1980年1月1日12点定义为MYNULLDATE。我在datetimepicker的文本和值上使用了数据绑定。我没有使用datetimepicker中的复选框。我也没有交替使用从短到自定义的格式。它似乎触发了valuechanged事件,所以我只使用了自定义,并更改了自定义格式。我使用了一个flowpanel和一个非绑定的复选框放在datetimepicker前面。
代码示例:
   private void dateTimePicker_ValueChanged(object sender, EventArgs e)
    {
        if (sender != null && sender.GetType() == typeof(DateTimePicker))
        {
            if (((DateTimePicker)(sender)).Value == MYNULLDATE)
            {
                ((DateTimePicker)(sender)).CustomFormat = " ";
                checkBoxDate.Checked = false;
            }
            else
            {
                ((DateTimePicker)(sender)).CustomFormat = "M/d/yyyy";
                checkBoxDate.Checked = true;
            }
        }

    }

在非绑定的复选框中

  private void checkBoxDate_Click(object sender, EventArgs e)
    {
        if (bindingSource != null && bindingSource.Current != null &&
             bindingSource.Current.GetType() == typeof(MyRecord))
        {
            MyRecord a = (MyRecord)bindingSource.Current;
            if (checkBoxDate.Checked == false)
            {
                a.Date = MYNULLDATE;
                dateTimePicker.Enabled = false;
            }
            else
            {
                if (a.Date == null || a.Date == MYNULLDATE)
                {
                    dateTimePicker.Enabled = true;
                    a.Date = DateTime.Now;
                }
            }
            bindingSource.ResetBindings(false);
        }
    }

2

我喜欢ShowCheckBox选项。我会更进一步,用两个扩展方法来封装它,以避免重复并使代码看起来更加清晰:

public static DateTime? NullableValue(this DateTimePicker dtp)
{
    return dtp.Checked ? dtp.Value : (DateTime?)null;
}

public static void NullableValue(this DateTimePicker dtp, DateTime? value)
{
    dtp.Checked = value.HasValue;
    if (value.HasValue) dtp.Value = value.Value;
}

然后,get和set的代码如下:
dtpSafetyApprover.NullableValue(model.SafetyApproverDate); // set
model.SafetyApproverDate = dtpSafetyApprover.NullableValue(); // get

2

最简单的方法是添加一个文本框并将可见属性设置为false。在日期选择器的valuechanged事件中,使用相同的日期时间值填充文本框。检查文本框的值是否为空字符串,如果是则将值设置为null。


0

使用Vs 2015并且无法绑定DateTimePicker控件。最简单的方法似乎是不要绑定它-手动将对象的值传递到控件,然后再从控件手动传递回对象。几行代码可以为您节省很多麻烦...

private void BindData()
{
    // can't bind the datetimepicker, so handle it manually...
    if (o.myDate == null)
    {
        dtDatePicker.Checked = false;
    }
    else
    {
        dtDatePicker.Checked = true;
        dtDatePicker.Value = o.myDate.Value;
    }
}

private void Save()
{
    if (dtDatePicker.Checked)
    {
        o.myDate = dtDatePicker.Value;
    }
    else
    {
        o.myDate = null;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接