Hero

Como crear un ASP.NET Ajax Server Control Extender personalizado en .Net 4.5

Febrero 04, 2013

spadillar
Microsoft
.Net
ASP.Net

En ocasiones los desarrolladores web, nos encontramos con la necesidad de encapsular cierta funcionalidad combinando el estado de uno o más controles desde el lado del cliente, para luego implementarlo de forma sencilla y ágil en varias secciones o forms en nuestro sitio. Lo anterior podemos lograrlo utilizando extenders de ASP.NET AJAX Toolkit http://ajaxcontroltoolkit.codeplex.com/ , cabe destacar que esta librería es muy completa y va a cubrir la mayoría de necesidades sin embargo en ocasiones la librería de Ajax disponible, no es suficiente para lo que queremos hacer o simplemente queremos nuestra propia funcionalidad desde cero.

En el siguiente ejemplo veremos cómo crear un AJAX Control Extender en el cual vamos a solicitarle al programador ciertas propiedades para determinar con cuales controles de servidor va a interactuar el extender.

Nuestro extender debe controlar que el usuario digite algún valor en el textbox de destino para habilitar un botón de continuar, o bien si eliminan el texto deshabilita nuevamente el botón de continuar y además muestra en un label de manera opcional un texto para indicarle al usuario que es obligatorio especificar el valor.

Para nuestro ejemplo vamos a utilizar ASP.NET 4.5 y Visual Studio 2012 y la solución se encuentra adjunta al final del artículo.

1. Creación de nuestro extender

Nuestro extender se llamará “RequiredFieldDisableButton” el cual tendrá las siguientes propiedades:

  • TargetControlID: Define el ID del textbox a validar.
  • TargetButtonID: Define el ID del botón que vamos a habilitar o deshabilitar.
  • TargetLabelID: Define el ID del label para mostrar nuestro mensaje de validación.
  • DisabledText: Define el texto que queremos mostrarle al usuario cuando la condición no se cumple.

Como es posible observar en la siguiente imagen el textbox de nombre de usuario se encuentra vació por lo tanto nuestro botón de continuar se encuentra deshabilitado y además nos aparece el mensaje de alerta.

Imagen1 1

Cuando se digita el nombre de usuario se puede observar como nuestro botón de continuar es habilitado y desaparece nuestro mensaje de alerta.

enabled

1.1 Agregar proyecto de librería de clases o ASP.NET Ajax Server Control Extender

Para la creación del extender vamos a agregar a nuestra solución un proyecto de tipo “ASP.NET AJAX Server Control Extender” o bien podemos agregar un proyecto “Class Library”.

addproject

Si creamos nuestros extenders en una librería de clases, debemos asegurarnos que el mismo incluya las siguientes referencias:

Adicionalmente verificar que nuestra aplicación web incluya la referencia a AjaxControlToolKit.dll

En nuestro proyecto de librería de clases o extenders de Ajax debemos crear los siguientes archivos:

  • RequiredFieldDisableButton.cs: Este archivo es la clase del control del lado del servidor la cual gestiona la creación del mismo y le permite al programador establecer las propiedades en tiempo de diseño.
  • RequiredFieldDisableButtonBehavior.js: En este archivo se especificará toda la lógica del lado del cliente.
  • RequiredFieldDisableButtonDesigner.cs: Esta clase activa la funcionalidad en tiempo de diseño para trabajar correctamente con el diseñador de Visual Studio.

1.2 Crear la clase RequiredFieldDisableButton.cs:

En este archivo debemos agregar las propiedades que tendrá nuestro extender, mismas que luego van a ser utilizadas en el behavior javascript.

Importante destacar que debemos registrar como webresource nuestro archivo .js con la lógica del lado del cliente:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using AjaxControlToolkit;
using System.ComponentModel;

[assembly: System.Web.UI.WebResource("CustomExtenders.RequiredFieldDisableButtonBehavior.js", "text/javascript")]
namespace CustomExtenders {
	/// <summary>
	/// RequiredFieldDisableButton
	/// </summary>	
	[TargetControlType(typeof(TextBox))]
	[ClientScriptResource("CustomExtenders.RequiredFieldDisableButtonBehavior", "CustomExtenders.RequiredFieldDisableButtonBehavior.js")]
	public class RequiredFieldDisableButton:ExtenderControlBase {

		[ExtenderControlProperty]
		[DefaultValue("")]
		[IDReferenceProperty(typeof(Button))]
		public string TargetButtonID {
			get {
				return GetPropertyValue("TargetButtonID", "");
				}
			set {
				SetPropertyValue("TargetButtonID", value);
				}
			}

		[ExtenderControlProperty]
		[DefaultValue("")]
		public string DisabledText {
			get {
				return GetPropertyValue("DisabledText", "");
				}
			set {
				SetPropertyValue("DisabledText", value);
				}
			}

		[ExtenderControlProperty]
		[DefaultValue("")]
		[IDReferenceProperty(typeof(Label))]
		public string TargetLabelID {
			get {
				return GetPropertyValue("TargetLabelID", "");
				}
			set {
				SetPropertyValue("TargetLabelID", value);
				}
			}
		}
	}

Nótese que nuestra clase debe heredar de ExtenderControlBase.

1.3 Crear la clase RequiredFieldDisableButtonBehavior.js:

Este archivo determinara el comportamiento de nuestro extender desde el lado del cliente, aca debemos declarar también nuestras propiedades mismas que especificamos en nuestro archivo RequiredFieldDisableButton.cs

Adicionalmente debemos determinar cuál evento vamos a utilizar para validar el control de destino, para nuestros efectos vamos a utilizar el evento keyup. Dentro del método initialize es necesario crear un delegado para el evento keyup donde especificaremos la lógica de validación que tendrá el mismo.

Type.registerNamespace("CustomExtenders");

CustomExtenders.RequiredFieldDisableButtonBehavior = function(element) {
    CustomExtenders.RequiredFieldDisableButtonBehavior.initializeBase(this, [element]);

    /* Declaración de variables de instancia */
    this._targetButtonIDValue = null;
    this._disabledTextValue = null;
    this.targetLabelIDValue = null;
}

CustomExtenders.RequiredFieldDisableButtonBehavior.prototype = {
    initialize: function() {
        // Inicialización
        CustomExtenders.RequiredFieldDisableButtonBehavior.callBaseMethod(this, 'initialize');
        
        // Agregar la inicialización personalizada aquí
        $addHandler(this.get_element(), 'keyup',
        Function.createDelegate(this, this._onkeyup));
        this._onkeyup();        
    },

    dispose: function() {                
        CustomExtenders.RequiredFieldDisableButtonBehavior.callBaseMethod(this, 'dispose');
    },

    // Propiedades:     
    get_TargetButtonID: function () {
        return this._targetButtonIDValue;
    },

    set_TargetButtonID: function (value) {
        this._targetButtonIDValue = value;
    },

    get_DisabledText: function () {
        return this._disabledTextValue;
    },

    set_DisabledText: function (value) {
        this._disabledTextValue = value;
    },

    get_TargetLabelID: function () {
        return this._targetLabelIDValue;
    },

    set_TargetLabelID: function (value) {
        this._targetLabelIDValue = value;
    },

    // Evento onKeyUp para el target textbox 
    _onkeyup: function () {
        var e = $get(this._targetButtonIDValue);
        var info = $get(this._targetLabelIDValue);

        if (e) {
            var disabled = ("" == this.get_element().value);
            e.disabled = disabled;            

            if (this._disabledTextValue) {
                if (disabled) {                    
                    info.innerText = this._disabledTextValue;
                }
                else {                    
                    info.innerText = "";                                                                    
                }
            }
        }
    }


}

CustomExtenders.RequiredFieldDisableButtonBehavior.registerClass('CustomExtenders.RequiredFieldDisableButtonBehavior', Sys.UI.Behavior);
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

1.4 Crear la clase RequiredFieldDisableButtonDesigner.cs:

Este archivo lo necesitamos únicamente si deseamos que el developer desde el diseñador de visual studio pueda utilizar o referenciar nuestro extender, es importante destacar que esta clase debe heredar desde AjaxControlToolkit.Design.ExtenderControlBaseDesigner<RequiredFieldDisableButton>:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AjaxControlToolkit;

namespace CustomExtenders {
	public class RequiredFieldDisableButtonDesigner:AjaxControlToolkit.Design.ExtenderControlBaseDesigner<RequiredFieldDisableButton> {

		}
	}
  1. Como utilizar nuestro extender en aplicaciones ASP.NET:

2.1 Referenciar nuestro proyecto de librería de clases o Ajax Extender Control o bien la dll de nuestro proyecto de extenders.

addreference

2.2 En las páginas donde utilizaremos nuestro control es necesario registrar el control ScriptManager el cual administra las bibliotecas de scripts y los archivos AJAX de ASP.NET

<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>

2.3 Implementar nuestro extender en los controles ASP.NET y configurar las propiedades correspondientes del mismo.

<asp:TextBox ID="txtUserName" runat="server"></asp:TextBox>
                    <cc1:RequiredFieldDisableButton ID="txtUserName_RequiredFieldDisableButton" runat="server" Enabled="True" TargetControlID="txtUserName" DisabledText="Por favor especifique el nombre del usuario." TargetButtonID="cmdNext" TargetLabelID="lblInfo">
                    </cc1:RequiredFieldDisableButton>

Debido a que creamos la clase para la funcionalidad en tiempo de diseño podemos también implementar nuestro extender con el diseñador de visual studio y el editor de propiedades.

addextender

properties

Recibe consejos y oportunidades de trabajo 100% remotas y en dólares de weKnow Inc.