Controles Personalizados en ASP.NET
Por: alex | 17 Julio 2006 | Ver comentarios |
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.
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.
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.

Finalmente, necesitamos que nuestro ensamblado permita que el archivo script.js
sea reconocido como recurso Web, para esto usamos el atributo
WebResource.
[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.


Diego
16 de Octubre de 2006, 09:29:40 pm
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:
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 NamespaceDesde ya agradeceré cualquier ayuda que puedan proporcionarme.
Saludos, Diego
alex
17 de Octubre de 2006, 09:56:08 pm
Diego, la implementación del control parece correcta, pero habría que ver como lo estás usando y qué resultados realmente esperas.
Saludos