Es posible que a muchos este título les suene a chino, y quizás también, no sea un caso que se de muy a menudo. Pero opino que es una característica que debemos conocer para tener más control sobre las aplicaciones ASP.NET AJAX.
El problema
Comenzemos plantenado el problema. Cuando utilizamos AJAX Extensions en una aplicación ASP.NET sabemos que en la respuesta asíncrona del servidor solo se envía de vuelta al cliente web una porción muy pequeña de HTML. Exactamente, solo se envía el HTML necesario para actualizar los controles que se encuentran dentro de un UpdatePanel, es lo que se conoce como repintado parcial. ¿Pero que ocurre si queremos, en algunas ocasiones, actualizar un control que se encuentra fuera de un UpdatePanel?. Es decir, ¿como podemos decirle al servidor que envíe otros datos además del HTML del repintado parcial?.
Veámoslo con un pequeño ejemplo.
<div>
<asp:TextBox ID="TextBox1" runat="server">
</asp:TextBox><asp:Button ID="Button1" runat="server" Text="Button"
onclick="Button1_Click" />
<br />
<br />
<!-----------Sección que se actualiza por AJAX (repintado parcial)--------------->
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</ContentTemplate>
<Triggers><asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" /></Triggers>
</asp:UpdatePanel>
<!-------------------------------------------------------------------------------->
<br />
<br />
<asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>
</div>
¿Que tenemos aquí?. Tenemos un TextBox donde el usuario introducirá su nombre y tenemos dos Labels que mostrarán un saludo al usuario cuando hagan Click sobre el Button. Como podemos observar uno de los Labels se encuentra dentro de un UpdatePanel y el otro fuera. El que esta dentro se aprovechará de la funcionalidad de AJAX para actualizar su contendido de manera asíncrona.
Añadamos código para manejar el evento del Button y veamos que sucede.
protected void Button1_Click(object sender, EventArgs e)
{
string datosEnviados = "Hola " + TextBox1.Text;
Label1.Text = datosEnviados;
Label2.Text = datosEnviados;
}
Al ejecutarse el evento vemos que solo se actualiza el Label1. El Label2 no se entera de nada. ¿Porque?.
Ya lo hemos comentado ante. El servidor solo está enviando al cliente el HTML necesario para actualizar los controles que se encuentran dentro del UpdatePanel.Repito la pregunta, ¿como podemos decirle al servidor que envíe otros datos además del HTML del repintado parcial?.
La solución
Cambiamos el código del evento del Button por el siguiente:
string datosEnviados = "Hola " + TextBox1.Text;
Label1.Text = datosEnviados;
ScriptManager1.RegisterDataItem(Label2, datosEnviados);
El método RegisterDataItem() del ScriptManager envía datos en una llamanda asíncrona a los controles que se encuentran fuera del UpdatePanel. Ahora debemos manegar el siguiente evento en el cliente.
<script type="text/javascript" language="javascript">
Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(RecogerDatosHandler);
function RecogerDatosHandler(sender, args) {
var datos = args.get_dataItems();
$get("Label2").innerHTML = datos["Label2"];
}
</script>
En primer lugar obtenemos una instancia de la clase Sys.WebFroms.PageRequestManager que es la encargada de actualizar los controles que se encuentran dentro del UpdatePanel. Antes de que esta actualización ocurra, gestionamos el evento pageLoading() y recogemos los datos enviados desde el servidor para actualizar el Label2.
Hemos creado nuestro propio manejador del evento, RecogerDatosHandler(), que por medio del la colección args podemos acceder a los datos enviados desde el servidor.
Nota: La definición del script cliente anterior debe colocarse después de la definición del controls ScriptManager, de lo contrario nos dará un error diciendo que el espacio de nombres Sys no está definico aún, ¡como es lógico!.