Как установить datetimepicker с нулевым значением, если дата не выбрана (С# winforms)

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 coming in as NULL
                // if i set to DateTime.Today, and that DIFFERENT than the control 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 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

Ответы

Ответ 1

DateTimePicker не может быть установлен в null, поскольку DateTime не может быть нулевым, но вы можете установить для них значение DateTime.MinValue, которое является значением по умолчанию для неинициализированного DateTime. И тогда вы просто проверяете, есть ли dtp.Value = DateTime.MinValue, и если да, относитесь к нему как к нулевому.

Однако, если вы хотите действительно отличить, когда значение не было выбрано, самый простой способ - установить DateTimePicker.ShowCheckBox на true, а затем вы проверите dtp.Checked, и если оно истинно, вы читаете значение, иначе вы будете лечить это как null.

Ответ 2

Вы можете проверить, отправляет ли ваш источник привязки "нулевую дату" или значение даты, которое вы не хотите отображать.

Если это так, выберите пользовательский формат:

yourDTP.Format = DateTimePickerFormat.Custom
yourDTP.CustomFormat = " "

Добавьте обработчик событий "CloseUp" или "ValueChanged" в reset формат действия пользователя:

yourDTP.Format = DateTimePickerFormat.Short

Ответ 3

Мне нравится опция 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

Ответ 4

Самый простой способ - добавить текстовое поле и установить для свойства visible значение false. В событии valuechanged элемента выбора даты заполняется текстовое поле с тем же значением времени даты элемента управления выбора. Проверьте значение текстового поля, если пустая строка задает значение null.

Ответ 5

вот как я решил это. Я не мог иметь NULLS, поэтому я определил 1/1/1980 12am как MYNULLDATE. Я использовал привязку данных по тексту и значению datetimepicker. Я не использовал этот флажок в datetimepicker. Я не использовал альтернативные форматы от коротких до обычных. Похоже, что он запускает события с измененными значениями, поэтому я просто использовал custom и изменил customformat. Я использовал поле flowpanel и NONBOUND, чтобы сидеть перед 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;
            }
        }

    }

В NonBound CheckBox

  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);
        }
    }

Ответ 6

Использование 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;
    }
}