Какой самый простой и надежный способ изменить элемент управления .NET DateTimePicker, чтобы пользователи могли вводить значения null?





Размещение дополнительного флажка, помеченного как «включить уведомление», который включает / отключает DateTimePicker.
Вот подход из этой статьи CodeProject по созданию Обнуляемый DateTimePicker.
I have overridden the
Valueproperty to acceptNullvalue asDateTime.MinValue, while maintaining the validation ofMinValueandMaxValueof the standard control.
Вот версия компонента пользовательского класса из статьи
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;
}
}
}
Да, NullableDateTimePicker мистера Грацоли выполняет свою работу, хотя я думаю, что кто-то должен его просмотреть и попытаться избавиться от этих уродливых вызовов WndProc
Еще одна особенность кода в том, что он, похоже, не делал того, что должен был делать. Не знаю, может я что-то делал не так. Не стоит тратить много времени на то, чтобы возиться с этим. Идея ShowCheckBox для DTP действительно кажется более многообещающей.
Хотя решение позволяет пользователю очистить дату, вы больше не можете устанавливать фокус на элемент управления или использовать клавиатуру для повторного ввода ненулевой даты. Один шаг вперед, два назад.
Решение Tri меня не совсем устраивало, поэтому подумал мистер Грациоли и что-то с этим сделал: http://www.codeguru.com/csharp/csharp/cs_controls/custom/article.php/c9645
Для этого вам не нужно изменять его.
DateTimePicker в .net фактически имеет встроенный флажок.
Установите для свойства ShowCheckBox значение true.
Затем вы можете использовать свойство Checked, чтобы узнать, ввел ли пользователь значение.
http://msdn.microsoft.com/en-us/library/system.windows.forms.datetimepicker.showcheckbox(VS.80).aspx
Однако реализация флажка дает сбой. Не запускает события должным образом.
Я опубликовал свое долгое решение, которое содержит некоторые выводы в комментариях к коду о специфических проблемах с этим элементом управления:
Установите для свойства ShowCheckBox значение true.
Затем вы можете использовать свойство Checked следующим образом:
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;
}
}
Другой вариант - использовать MaskedTextBox с маской
00/00/0000. Это обеспечивает несколько интуитивно понятный ввод данных и, вероятно, наиболее интуитивно понятный UX для резервного копирования поля даты.