Как установить 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;
}
}