ASP.Net: Crear un control de servidor. Ejemplo: JnTextBoxNif

En el post anterior, Validar CIF, NIF, NIE me comprometí a explicar cómo hacer uso de la clase JnSoftware.Validaciones.NumeroNif para validar un documento introducido en una página ASP.NET. Debo confesar que el motivo inicial era crear un control de usuario en el que se validase dicho documento embebido dentro de un UpdatePanel. Como hasta el momento no había creado nunca un control de servidor, reconozco que ha podido más la curiosidad que otra cosa y al final, después de algún que otro problema, he creado un control de servidor que permite validar y normalizar un documento, sea CIF, NIF o NIE. De este modo, según mi parecer, nos encontramos con un mayor nivel de reusabilidad.

Antes de nada me gustaría comentar que en las aplicaciones que creo siempre dejo que se introduzca cualquier número en el campo NIF. Sencillamente, lo que hago es que, cuando no es un documento validado lo resalto con un color rojo de fondo que traspasa al usuario la responsabilidad de aceptar o no la entrada.

Pongámonos manos a la obra. Lo primero que deberemos crear es un proyecto que incluya los controles de servidor. En el caso que nos conlleva ahora sólo introduciremos el control JnTextBoxNif, pero ahora que empiezo a verle la utilidad a este tipo de controles, seguro que no será el único.

image

Automáticamente, VisualStudio crea, dentro del proyecto, una clase ServerControl1.cs con la estructura básica. Yo, lo que suelo hacer es eliminar este control y crear uno nuevo. Para ello, le indico que quiero crear un nuevo Control de Servidor.

image

No debemos olvidar incluir un par de referencias en el proyecto, por un lado, la referencia a la DLL creada en el post anterior que incluirá la validación del número CIF, NIF, NIE (JnSoftware.Validaciones) y, por otro, como haremos uso de un control UpdatePanel para que se actualice sólo el contenido del control de usuario a la librería System.Web.Extensions, que incluye, entre otros, dicho UpdatePanel.

using System;
using System.ComponentModel;
using System.Drawing;
using System.Web.UI;
using System.Web.UI.WebControls;
using JnSoftware.Validaciones;

/* Asigna el nombre automáticamente de la etiqueta del control */
[assembly: TagPrefix("JnSoftware.WebControls", "JnControl")]

namespace JnSoftware.WebControls
{
    [ToolboxData("<{0}:JnTextBoxNif runat=server></{0}:JnTextBoxNif>")]
    [Designer("JnSoftware.WebControls.JnTextBoxNifControlDesigner, JnSoftware.WebControls")]
    [Description("Permite la validación de un NIF,CIF,NIE")]
    [DefaultProperty("Text")]
    public class JnTextBoxNif : WebControl
    {

        #region Campos
        // Texbox sobre el que se validará el documento
        TextBox txtNif = new TextBox();

        // UpdatePanel para que se actualice sólo el control
        UpdatePanel updatePanel = new UpdatePanel();
        #endregion

        
        #region Control en modo de diseño

        /* En modo de diseño, se mostrará un Input de HTML */
        private string renderHtml = "<input type="text"  value="{0}"/>";
        
        internal string RenderHtml
        {
            get { return string.Format(renderHtml, txtNif.ID); }
        }
        
        #endregion


        [Bindable(true), Category("Appearence")]
        public string Text
        {
            get { return txtNif.Text; }
            set { txtNif.Text = value; compruebaNif(); }
        }


        protected override void OnLoad(EventArgs e)
        {
            controlesPanel();
            base.OnLoad(e);
        }

        
        /// <summary>
        /// Carga los elementos del control 
        /// </summary>
        private void controlesPanel()
        {
            // Textbox sobre el que se realizará la validación
            txtNif.ID = ID + "_txtNif";
            txtNif.AutoPostBack = true;
            txtNif.TextChanged += new EventHandler(txtNif_TextChanged);

            // UpdatePanel
            Control container = updatePanel.ContentTemplateContainer;
            
             // Si no se establece el modo de actualización del UpdatePanel 
             // como Conditional, al actualizar un updatePanel en la página, 
             // se actualizan todos 
            updatePanel.UpdateMode = UpdatePanelUpdateMode.Conditional;
            updatePanel.RenderMode = UpdatePanelRenderMode.Inline;

            // Se añaden los controles
            container.Controls.Add(txtNif);
            base.Controls.Add(updatePanel);
        }



        void txtNif_TextChanged(object sender, EventArgs e)
        {
            compruebaNif();
        }


        #region Cálculos internos

        /// <summary>
        /// Comprueba que el Nif introducido sea correcto.
        /// </summary>
        private void compruebaNif()
        {
            string nif = txtNif.Text;
            try
            {
                if (!string.IsNullOrEmpty(nif))
                {
                    NumeroNif numero = NumeroNif.CompruebaNif(nif);
                    if (!numero.EsCorrecto)
                        throw new ApplicationException("Número no válido");
                    txtNif.Text = numero.ToString();
                }
                formatoTextBox(true);
            }
            catch
            {
                formatoTextBox(false);
            }
        }


        /// <summary>
        /// Aplica un formato personalizado al TextBox en base 
        /// al resultado de la validación del documento
        /// </summary>
        /// <param name="validado">True si es un documento correcto</param>
        private void formatoTextBox(bool validado)
        {
            Color colorFondo = Color.Empty;
            if (!validado)
                colorFondo = Color.Red;
            txtNif.BackColor = colorFondo;
        }

        #endregion
    }
}
 

Aunque he incluido la clase una vez finalizada, se puede apreciar que no reviste gran dificultad, puesto que son pocos los métodos que realmente tienen una gran trascendencia en el conjunto.

  • controlesPanel, que realiza la carga de los elementos que se incluirán dentro del UpdatePanel (en el ejemplo tan sólo existe el TextBox que nos permitirá introducir y validar el NIF, CIF, NIE).
  • compruebaNif, que es el método responsable de comprobar el documento introducido y, gracias a formatoTextBox, de aplicar un formato destacado en caso de no ser válido.

Ahora bien, una vez finalizada la clase, ya la veo hasta bonita, pero reconozco que me ha costado un buen rato descubrir los puntos siguientes:

  • Si creaba, dentro de una misma página varios controles JnTextBoxNif, en el momento que actualizaba uno, se actualizaban también todos los demás. Esto es consecuencia del modo de actualización de los diferentes UpdatePanel (uno por cada control). El modo de solventar este problema es cambiar el modo de actualización del UpdatePanel a Conditional.
  • Quizás sea una tontería, pero personalmente suele molestarme mucho que, cuando añado controles personales en una página, si me limito a arrastrar el componente desde la pantalla de diseño, VisualStudio le asigna un prefijo automático del tipo TagPrefix=”cc1”. Solvento este problema con la etiqueta [assembly] para que todos los controles tengan el mismo prefijo en la página.
  • Otra sorpresa: aunque el control funciona perfectamente en tiempo de ejecución, resulta que en vista de diseño no se muestra absolutamente nada. Para “mostrar algo” cuando esté trabajando en el modo de diseño me fijo en la clase System.Web.UI.Design.ControlDesigner, que me obliga a añadir una referencia nueva, System.Design. Una vez añadida dicha referencia, heredo de la clase ControlDesigner para que se muestre en tiempo de diseño un elemento similar al del TextBox (un Input de HTML, por ejemplo).
using System;

namespace JnSoftware.WebControls
{
    class JnTextBoxNifControlDesigner : System.Web.UI.Design.ControlDesigner
    {
        public override string GetDesignTimeHtml()
        {
            JnTextBoxNif t = (JnTextBoxNif)Component;
            return t.RenderHtml;
        }
    }
}

 

Cuando ya tenemos el control diseñado es hora de probarlo, así que creo un nuevo proyecto Web dentro de la misma solución y le añado la referencia correspondiente del proyecto JnSoftware.WebControls. Aunque añadir un nuevo control es tan sólo arrastrar el control que nos encontramos en el cuadro de herramientas, dejo constancia del código de la página puesto que así, evito olvidarme de recordar que debemos añadir un ScriptManager en la página para que funcione correctamente el UpdatePanel:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestNif.aspx.cs" Inherits="WebPresentacion.TestNif" %>
<%@ Register Assembly="JnSoftware.WebControls" Namespace="JnSoftware.WebControls" TagPrefix="JnControl" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="sm" runat="server" />
    <div>
        NIF 1: <JnControl:JnTextBoxNif ID="JnTextBoxNif1" runat="server" /><br />
        NIF 2: <JnControl:JnTextBoxNif ID="JnTextBoxNif2" runat="server" /><br />
    </div>
    </form>
</body>
</html>

One thought on “ASP.Net: Crear un control de servidor. Ejemplo: JnTextBoxNif

  1. excelente…
    Me quedan dudas de como construir un control nuevo, como graficarlo, como definir que partes del control son de entrada de datos y como se rescatan los datos de este control creado,…
    Pero el proceso de crear y usar controles de servidor me quedo claro.

    Gracias… geeks.ms a favoritos

Responder a anonymous Cancelar respuesta

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