NullableDateTimePicker
Una de las solicitudes habituales de los usuarios, cuando desarrollamos una aplicación Windows Forms en .Net, es que si no se selecciona ninguna fecha en un control DateTimePicker, no aparezca ninguna fecha reflejada.
El control DateTimePicker se puede configurar para que muestre un CheckBox, y si este no está seleccionado la fecha se difumina dando apariencia de no estar habilitada, pero los usuarios prefieren que no aparezca fecha alguna: este es el aspecto que he implementado en NullableDateTimePicker.
NullableDateTimePicker es una clase que hereda de DateTimePicker, en la que he implementado dos propiedades, ocultado otras dos e implementado un controlador de evento.
Lo primero es importar los espacios de nombres necesarios, que en este caso son tres.
using System;
using System.ComponentModel;
using System.Windows.Forms;
En realidad System.ComponentModel no es necesario, pero a mi personalmente me gusta dejarlo todo lo máximo documentado posible. Con System.ComponentModel añado descripciones a las propiedades para que aparezcan en tiempo de diseño y las incluyo en la categoría que creo conveniente (esto lo podéis adaptar a vuestro gusto). También limito que quiero que se muestre en tiempo de diseño.
Lo siguiente es implementar dos propiedades para indicar el formato en el que se debe mostrar la fecha cuando se muestra el CheckBox y esta chequedao, DefaultFormat, y el formato cuando se muestra el CheckBox y no está chequeado, NullFormat.
public DateTimePickerFormat DefaultFormat { get; set; }
public DateTimePickerFormat NullFormat { get; set; }
Hay dos propiedades de DateTimePicker que vamos a usar, pero las vamos a ocultar con nuestra implementación para que funcionen de manera distinta a como lo hacen, Checked y Format.
public new bool Checked
{
get
{
return base.Checked;
}
set
{
base.Checked = value;
this.OnValueChanged(new EventArgs());
}
}
public new DateTimePickerFormat Format
{
get
{
return base.Format;
}
internal set
{
base.Format = value;
}
}
En el caso de Checked, la única diferencia es que desencadena el evento ValueChanged, y dado que Checked no es virtual, he tenido que ocultarla.
En el caso de Format, quiero que el valor no se pueda asignar directamente, por eso he cambiado el modificador de set y lo he puesto como internal. Como se verá en el código final, he usado System.ComponentModel para que la propiedad Format no sea accesible en tiempo de diseño.
He implementado un constructor para asignar valores por defecto a las propiedades cuando se agrega el control desde el cuadro de herramientas a, por ejemplo, un formulario.
public NullableDateTimePicker()
{
this.DefaultFormat = this.NullFormat = DateTimePickerFormat.Long;
this.Format = this.Checked ? this.DefaultFormat : this.NullFormat;
this.ValueChanged += this.NullableDateTimePicker_ValueChanged;
}
Como podéis ver, también he añadido un controlador al evento ValueChanged de DateTimePicker.
Por último, he implementado dicho controlador para cambiar el formato dependiendo de si CheckBox está o no chequeado.
private void NullableDateTimePicker_ValueChanged(object sender, EventArgs e)
{
this.Format = this.Checked ? this.DefaultFormat : this.NullFormat;
}
Y con esto ya tenemos todo lo necesario para que, cuando mostremos el CheckBox y borremos la fecha, el control no muestre nada. Para que se comporte de esta manera tenéis que configurar el control de la siguiente manera.
ShowCheckBox = true
NullFormat = CustomFormat
CustomFormat = " "
Una última cosa a tener en cuenta es a la hora de enlazar el control con una propiedad, de por ejemplo una clase, de tal manera que cuando cambie la propiedad de la clase se actualice el valor del control y viceversa, es la forma en la que lo debemos implementar.
clase.Fecha = nullableDateTimePicker.Checked ? nullableDateTimePicker.Value.Date : null;
if (clase.Fecha.HasValue)
{
nullableDateTimePicker.Value = clase.Fecha.Value;
nullableDateTimePicker.Checked = true;
}
else
{
nullableDateTimePicker.Checked = false;
}
NullableDateTimePicker, el resultado final
Y éste es el resultado final de la clase. Cambiadlo y adaptadlo a vuestro gusto, si algo os parece que no está bien mejoradlo, pero sobre todo no os limitéis a copiarlo, intentad entenderlo. Seguro que hay otras formas de implementarlo.
namespace Espamatica.Windows.Forms
{
#region Includes
using System;
using System.ComponentModel;
using System.Windows.Forms;
#endregion
/// <summary>
/// <para>NullableDateTimePicker que permite mostrar la fecha en blanco cuando se muestra el CheckBox y Checked es false.</para>
/// <para>Valores a proporcionar:</para>
/// <para>DefaultFormat: formato de la fecha cuando Checked = true.</para>
/// <para>NullFormat: formato de la fecha cuando Checked = true (Custom para que no muestre nada).</para>
/// <para>CustomFormat: espacio en blanco para que no muestre nada.</para>
/// </summary>
public class NullableDateTimePicker : DateTimePicker
{
#region Constructores
/// <summary>
/// Incializa una nueva instancia de la clase NullableDateTimePicker.
/// </summary>
public NullableDateTimePicker()
{
this.DefaultFormat = this.NullFormat = DateTimePickerFormat.Long;
this.Format = this.Checked ? this.DefaultFormat : this.NullFormat;
this.ValueChanged += this.NullableDateTimePicker_ValueChanged;
} // NullableDateTimePicker
#endregion
#region Propiedades públicas
/// <summary>
/// Obtiene o establece un valor que indica si la propiedad System.Windows.Forms.DateTimePicker.Value
/// se ha establecido con un valor de fecha y hora válido, y si el valor mostrado
/// se puede actualizar.
/// </summary>
[Category("Comportamiento")]
[Description("Cuando ShowSelectBox está establecida en true, determina si la casilla está activada, indicando que el usuario ha seleccionado un valor.")]
public new bool Checked
{
get
{
return base.Checked;
}
set
{
base.Checked = value;
this.OnValueChanged(new EventArgs());
}
} // Checked
/// <summary>
/// Obtiene o establece el formato por defecto en el que se muestra el valor cuando Checked = true.
/// </summary>
[Category("Apariencia")]
[Description("Obtiene o establece el formato por defecto en el que se muestra el valor cuando checked = true.")]
public DateTimePickerFormat DefaultFormat { get; set; }
/// <summary>
/// Obtiene o establece el formato.
/// </summary>
[Browsable(false)]
[Category("Apariencia")]
[Description("Obtiene o establece el formato.")]
public new DateTimePickerFormat Format
{
get
{
return base.Format;
}
internal set
{
base.Format = value;
}
} // Format
/// <summary>
/// Obtiene o establece el formato por defecto en el que se muestra el valor cuando Checked = false.
/// </summary>
[Category("Apariencia")]
[Description("Obtiene o establece el formato por defecto en el que se muestra el valor cuando Checked = false.")]
public DateTimePickerFormat NullFormat { get; set; }
#endregion
#region Métodos privados
/// <summary>
/// Controlador del evento ValueChanged de NullableDateTimePicker.
/// </summary>
/// <param name="sender">Objeto que desencadena el evento.</param>
/// <param name="e">Datos del evento.</param>
private void NullableDateTimePicker_ValueChanged(object sender, EventArgs e)
{
this.Format = this.Checked ? this.DefaultFormat : this.NullFormat;
} // NullableDateTimePicker_ValueChanged
#endregion
} // NullableDateTimePicker
} // Espamatica.Windows.Forms
También puedes visitar el resto de tutoriales:
Y recuerda, si lo usas no te limites a copiarlo, intenta entenderlo y adaptarlo a tus necesidades.