NullableDateTimePicker

Una de las solicitudes habituales de los usuarios, cuando desarrollamos una aplicación Windows Forms, 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.

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

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
NullableDateTimePicker

Aquí puedes ver más cosas que he desarrollado para .Net, y aquí la desarrolladas en ensamblador para Z80.

Y recuerda, si lo usas no te limites a copiarlo, intenta entenderlo y adaptarlo a tus necesidades.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR
Aviso de cookies
A %d blogueros les gusta esto: