Categories
.NET Artí­culos ASP.NET

Controles Personalizados en ASP.NET

En esta oportunidad quiero mostrar un ejemplo sencillo de como realizar un
control personalizado
, éste simplemente va a extender el control TextBox
que trae el .NET Framework, haciendo que sólo acepte valores definidos en una expresión
regular.

Nuestra clase tendrá dos atributos: characterExpression y validationExpression,
el primero será la expresión regular que controle si una letra es válida o no (Ej.
\d si se desea que sólo acepte números), mientras que el segundo sirve para validar
el valor final (Ej. \d{3} para un número con tres dígitos).

A continuación sobre-escribiremos los métodos AddAttributesToRender -donde agregamos
los eventos de cliente onkeypress/onchange- y OnPreRender, en el cuál se registra
la referencia al código de cliente que está como recurso embedido.

csharp:

protected override void AddAttributesToRender(HtmlTextWriter writer)
{
        if (!string.IsNullOrEmpty(characterExpression))
                Utils.AddAttribute(this, "onkeypress",
                                        string.Format("bc_ValidarCaracter(event, '{0}')",
                                                characterExpression.Replace("\", "\\").Replace("'", "\'")));

        if (!string.IsNullOrEmpty(validationExpression))
                Utils.AddAttribute(this, "onchange",
                                        string.Format("bc_LimpiarValor(this, '{0}')",
                                                validationExpression.Replace("\", "\\").Replace("'", "\'")));

        base.AddAttributesToRender(writer);
}

protected override void OnPreRender(EventArgs e)
{
        base.OnPreRender(e);
        if (!string.IsNullOrEmpty(characterExpression) || !string.IsNullOrEmpty(validationExpression))
                Page.ClientScript.RegisterClientScriptResource(GetType(), "Buayacorp.Web.Resources.script.js");
}

Un aspecto importante al desarrollar este tipo de controles, es decidir cómo mantener
el estado de las propiedades del control, hasta antes de ASP.NET 2, esto normalmente
se realizaba utilizando el ViewState, dichos controles funcionaban bien siempre
y cuando esta característica haya sido habilitada, sin embargo ahora existe algo
que se llama "Control
State
", el cuál permite almacenar las propiedades no importando si el ViewState
está habilitado o no, cabe aclarar que ésta característica de manera predeterminada
 hace uso del mismo campo que utiliza el ViewState.

Utilice el estado del control sólo para pequeñas
cantidades de datos críticos que sean esenciales para el control en las distintas
devoluciones de datos. No debe utilizar el estado del control como alternativa al
estado de vista.

Una vez aclarado estos conceptos, considero que nuestro control debe tener datos
válidos no importando si el ViewState está habilitado o no.

csharp:

protected override void OnInit(EventArgs e)
{
        Page.RegisterRequiresControlState(this);
        base.OnInit(e);
}
protected override object SaveControlState()
{
        Pair state = new Pair();
        state.First = base.SaveControlState();

        state.Second = new string[] { characterExpression, validationExpression };

        return state;
}

protected override void LoadControlState(object state)
{
        Pair p = state as Pair;
        if (p != null)
        {
                base.LoadControlState(p.First);

                string[] v = p.Second as string[];

                if (v != null)
                {
                        characterExpression = v[0];
                        validationExpression = v[1];
                }
        }
}

A continuación ponemos el siguiente código en el archivo script.js, que será un
recurso embedido del ensamblado de nuestro control.

Código Javascript

Finalmente, necesitamos que nuestro ensamblado permita que el archivo script.js
sea reconocido como recurso Web, para esto usamos el atributo
WebResource
.

csharp:

[assembly: System.Web.UI.WebResource("Buayacorp.Web.Resources.script.js",
                "text/javascript")]

Happy coding!

Archivos Relacionados

Nota: el código javascript está mostrado como imagen debido a que tenemos ciertas restricciones por el mod_security de nuestro hosting.

3 replies on “Controles Personalizados en ASP.NET”

[...] En la entrada anterior, vimos como extender el control TextBox (del .NET Framework) para restringir la entrada a sólo ciertos caracteres definidos en una expresión regular. Pues bien, en esta ocasión vamos a crear un control que ayudará a medir la popularidad de algún artículo o comentario. [...]

Hola, he estado investigando el uso de ControlState y he hecho algunos ejemplos de prueba pero se me presenta el problema de que cuando ejecuto paso a paso el código, sí entra al SaveControlState pero nunca entra a LoasControlState por lo cual nunca puedo recuperar el estado guardado en el postback anterior. No sé si esté método es invocado por el mismo .NET Framework al cargar el formulario o si debo invocarlo yo manualmente desde algún lado.
El código de ejemplo es el siguiente:

vbnet:

Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls

Namespace DJ
    Public Class ControlDJ
        Inherits WebControl
        Implements INamingContainer

        Private _objeto As Object

        Public Property SelectedObject() As Object
            Get
                Return _objeto
            End Get
            Set(ByVal Value As Object)
                _objeto = Value
            End Set
        End Property

        Protected Overrides Sub CreateChildControls()
            If Not Page.IsPostBack Then
                Dim boton1 As New Button
                boton1.ID = "boton1"
                boton1.Text = "Enviar"
                Me.Controls.Add(boton1)
            End If
        End Sub

        Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
            Page.RegisterRequiresControlState(Me)
            MyBase.OnInit(e)
        End Sub

        Protected Overrides Function SaveControlState() As Object
            Dim obj As Object = MyBase.SaveControlState()

            If obj IsNot Nothing Then
                Return New Pair(obj, _objeto)
            Else
                Return _objeto
            End If

        End Function

        Protected Overrides Sub LoadControlState(ByVal state As Object)
            If (state IsNot Nothing) Then
                Dim p As Pair = TryCast(state, Pair)
                If p IsNot Nothing Then
                    MyBase.LoadControlState(p.First)
                    _objeto = p.Second
                Else
                    _objeto = state
                End If
            End If
        End Sub

    End Class
End Namespace

Desde ya agradeceré cualquier ayuda que puedan proporcionarme.
Saludos, Diego

Diego, la implementación del control parece correcta, pero habría que ver como lo estás usando y qué resultados realmente esperas.

Saludos

Comments are closed.