Ya he escrito en otras ocasiones sobre la cuestión de modificar la salida de las páginas ASPX y los controles, para poder modificarla a nuestra voluntad sin necesidad de tener acceso al código fuente (ver enlaces al final del post).

En esta ocasión voy a comentar una característica muy poco conocida de los controles que permite modificar su salida directamente, sin necesidad de heredar de ellos (técnica habitual) ni otras técnicas complicadas. Lo que haremos será sacar provecho a un método de la clase System.Web.UI.Control supuestamente pensado sólo para uso interno, pero que Microsoft ha dejado como público y por lo tanto acesible directamente a cualquiera.

Se trata del método SetRenderMethodDelegate. Éste permite asignar un delegado de una función de tipo RenderMethod que sustituirá al método de renderizado del control en cuestión. El método propio que definamos para asignar con SetRenderMethodDelegate toma dos parámetros: un HtmlTextWriter que utilizaremos para generar la salida del control, y una referencia al control cuyo método hemos sustituido.

Veámoslo con un ejemplo sencillo. Crea una página nueva y añádele una etiqueta, un cuadro de texto, un botón y otra etiqueta debajo, así:

Lo que haremos será que al pulsar el botón se mostrará "Hola" y el nombre introducido en el cuadro de texto en la segunda etiqueta que hemos añadido, así:

    protected void Button1_Click(object sender, EventArgs e)
    {
        Label2.Text = "Hola " + TextBox1.Text;
    }

Más sencillo imposible.

Vale. Ahora vamos a modificar el HTML que renderiza la segunda etiqueta para que, si hay algo escrito en el cuadro de texto, se haga caso omiso del renderizado por defecto de Label2 (que pondría "Hola " seguido del texto introducido en el cuadro de texto), y ponga otra cosa cualquiera.

Lo que haremos es crear un método propio de renderizado que se ciña al delegado RenderControl:

    protected void RenderPropioParaLabel(HtmlTextWriter output, Control container)
    {
        if (TextBox1.Text != "")
            output.Write("<b>Aquí</b> pongo lo que me da la gana " + TextBox1.Text);
        
    }

Ahora, en el evento Load de la página asignamos este método como método de render del control:

    protected void Page_Load(object sender, EventArgs e)
    {
        this.Label2.SetRenderMethodDelegate(this.RenderPropioParaLabel);
    }

Si ahora ejecutamos la página veremos que en lugar del texto asignado en el evento de pulsación del botón, lo que tenemos es una frase como esta: "Aquí pongo lo que me da la gana, Jose", con la primera palabra en negrita.

Evidentemente este ejemplo es una tontería, hecha sólo a modo de prueba de concepto de cómo hacer esto. Esta técnica sirve para modificar el renderizado de un control en una página concreta en la que el HTML que genera por defecto no es el que nos interesa.

Una limitación importante de este técnica a tener en cuenta es que no podremos obtener el renderizado por defecto del control y luego moificarlo (para esto hay otras técnicas, ver enlaces abajo), sino que tendremos que generar directamente todo el nuevo HTML para el control que estamos interceptando. Por supuesto no podremos llamar al método Render del control para obtener su HTML por defecto ya que éste lo que hace es llamar de nuevo a nuestro método de Render que ha sustituido al original, y entraríamos en un bucle infinito (prueba a poner container.Render() dentro de tu método de renderizado, ya verás).

Otra cuestión importante que debemos tener en cuenta es que esta técnica no funcionará con todos los controles, ya que depende de cómo estén éstos implementados internamente. Mientras el método Render del control llame al método Render del control base System.Web.UI.Control entonces funcionará. Si omite esta llamada (no es obligatorio en absoluto), entonces no funcionará. Lable llama al método de la base, pero la mayoría de los controles no lo hacen.

Entonces ¿para qué nos puede servir más allá de las etiquetas (que sería algo más bien pobre)?

Pues por ejemplo, la clase Page que hereda también de Control puede usar esta técnica, así que se pouede usar como alternativa a lo explicado en el primer artículo reseñado abajo.

Además hay controles sencillos que forman parte de controles más complejos y que se pueden modificar de este modo. Por ejemplo, los controles que representan las celdas de una tabla en una rejilla. Un ejemplo interesante de esto es modificar la cabecera de un GridView de modo que se renderice de otro modo y añada por ejemplo cabeceras extra dea agrupamiento.

En general podremos usar esta técnica con controles en los que nos fijemos en su código fuente y usen directamente el método Render de la clase base System.Web.UI.Control, que son más de los que parece, y la mayoría son controles contenedores de otros o controles muy sencillos.

Esta técnica es la que usa la propia infraestructura de ASP.NET para evaluar los bloques de codigo en el marcado de la página que son del tipo <% %> y <%= %> (no así las expresiones de binding <%# %> que funcionan de otro modo, en tiempo de ejecución). Si vamos al directorio temporal de ASP.NET y examinamos el código fuente generado automáticamente para cualquier página podemos verlo de forma clara.

Otros textos relacionados:

💪🏻 ¿Este post te ha ayudado?, ¿has aprendido algo nuevo?
Pues NO te pido que me invites a un café... Te pido algo más fácil y mucho mejor

Escrito por un humano, no por una IA