Cuadros de mensaje estilo MessageBox en AJAX usando ModalPopupExtender
Como ya hemos tratado anteriormente en este blog, el control ModalPopupExtender, incluido en el Ajax Control Toolkit, permite la construcción de paneles con un funcionamiento semejante al de una ventana de diálogo.
Tomando como base este comportamiento, una posible finalidad a la que podríamos destinar el uso de este control consistiría en crear un cuadro de diálogo, con una funcionalidad similar a la ofrecida por la clase MessageBox de Windows Forms, o la función alert de JavaScript; es decir, presentar al usuario una ventana con un título, un texto representativo del mensaje, un icono y uno o dos botones para proporcionar la respuesta al mensaje.
Supongamos que nos encontramos desarrollando una página Web en la que se solicita al usuario un nombre y clave para realizar un proceso de identificación, pero en el caso de que los datos introducidos no sean correctos, necesitamos mostrar un pequeño aviso en forma de cuadro de diálogo informativo del problema ocurrido.
Para el código de marcado correspondiente al formulario de introducción de los datos emplearemos el siguiente código fuente.
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<table border="2">
<tr>
<td colspan="2" align="center">
<asp:Label ID="Label1" runat="server" Text="Datos de acceso" Font-Bold="True" Font-Underline="True" />
</td>
</tr>
<tr>
<td>
<asp:Label ID="Label2" runat="server" Text="Nombre:" />
</td>
<td>
<asp:TextBox ID="txtNombre" runat="server" />
</td>
</tr>
<tr>
<td>
<asp:Label ID="Label3" runat="server" Text="Clave:" />
</td>
<td>
<asp:TextBox ID="txtClave" runat="server" />
</td>
</tr>
<tr>
<td colspan="2" align="center">
<asp:Button ID="btnEntrar" runat="server" Text="Entrar" Style="margin: 5px;" OnClick="btnEntrar_Click" />
<br />
<asp:Label ID="lblAccesoPermitido" runat="server" Text="Acceso permitido" Visible="False" />
</td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
Cabe destacar el control Label lblAccesoPermitido, que inicialmente no se visualiza, ya que será utilizado para mostrar un literal al usuario cuando haya introducido correctamente los datos de acceso. También es importante señalar los elementos ScriptManager y UpdatePanel añadidos a la página, que nos servirán para dotar a esta de la funcionalidad AJAX necesaria en el ejemplo.
En tiempo de ejecución, esta página Web mostrará el siguiente aspecto.

El code-behind correspondiente al botón btnEntrar es el siguiente.
protected void btnEntrar_Click(object sender, EventArgs e)
{
// si los datos de acceso son correctos
// se muestra el literal que indica dicho estado
if (this.txtNombre.Text == "Elena" && this.txtClave.Text == "123")
{
this.lblAccesoPermitido.Visible = true;
}
}
En lo que respecta a la caja de mensajes, su composición estará formada por un conjunto de controles Button, Label, Image, etc., contenidos dentro de un Panel, al que aplicaremos un estilo para mejorar su presentación.
<style type="text/css">
.CajaDialogo
{
background-color: #99ffcc;
border-width: 4px;
border-style: outset;
border-color: Yellow;
padding: 0px;
width: 275px;
font-weight: bold;
font-style: italic;
}
.CajaDialogo div
{
margin: 7px;
text-align: center;
}
….
….
</style>
<asp:Panel ID="pnlMensaje" runat="server" CssClass="CajaDialogo" style="display: none;">
<table border="0" width="275px"
style="margin: 0px; padding: 0px; background-color: #0033CC; color: #FFFFFF;">
<tr>
<td align="center">
<asp:Label ID="Label5" runat="server" Text="¡ Atención !" />
</td>
<td width="12%">
<asp:ImageButton ID="btnCerrar" runat="server" ImageUrl="Cerrar.jpg"
Style="vertical-align: top;" ImageAlign="Right" />
</td>
</tr>
</table>
<div>
<asp:Image ID="imgIcono" runat="server" ImageUrl="Exclama.jpg" BorderColor="Black"
BorderStyle="Solid" BorderWidth="1px" ImageAlign="Middle" />
<asp:Label ID="Label7" runat="server" Text="Datos de usuario incorrectos" />
</div>
<div>
<asp:Button ID="btnAceptar" runat="server" Text="Aceptar" />
</div>
</asp:Panel>
En la siguiente figura podemos apreciar el aspecto de nuestra caja de mensajes.

A continuación añadiremos al formulario Web el control ModalPopupExtender, que será el encargado de visualizar el Panel anterior con el comportamiento de una caja modal de mensajes.
<cc1:ModalPopupExtender ID="mpeMensaje" runat="server" TargetControlID="btnEntrar"
PopupControlID="pnlMensaje"
BackgroundCssClass="FondoAplicacion"
OkControlID="btnAceptar"
OnOkScript="mpeMensajeOnOk()" />
En caso de que pulsemos el botón btnAceptar del cuadro de diálogo, se ejecutará la siguiente función JavaScript, que está asociada a dicho botón mediante la propiedad OnOkScript del ModalPopupExtender. La tarea de dicha función consistirá en borrar el contenido de los TextBox de la página, situando el foco en el primero de ellos.
<script language="javascript" type="text/javascript">
function mpeMensajeOnOk()
{
var txtNombre = document.getElementById("txtNombre");
var txtClave = document.getElementById("txtClave");
txtNombre.value = "";
txtClave.value = "";
txtNombre.focus();
}
</script>
Si por el contrario pulsamos el ImageButton btnCerrar -que simula el botón de cierre de una ventana-, el diálogo se cerrará sin realizar acción alguna.
Mientras que la caja de mensajes se visualice, el resto de elementos de la página estarán deshabilitados; para que visualmente esto se perciba mejor, vamos a crear un estilo que asignaremos a la propiedad BackgroundCssClass del extensor. Como resultado, el control ModalPopupExtender aplicará este estilo a todos los elementos de la página que no sean los correspondientes al Panel.
<style type="text/css">
….
….
.FondoAplicacion
{
background-color: Gray;
filter: alpha(opacity=70);
opacity: 0.7;
}
</style>
Una vez terminado todo este trabajo ya podemos poner en ejecución nuestro programa. Sin embargo vamos a encontrarnos con el siguiente problema: cuando pulsemos el botón btnEntrar, el ModalPopupExtender siempre va a mostrar el cuadro de mensajes, aunque los datos de acceso sean correctos y no deba por tanto visualizarse el cuadro modal. Este comportamiento es motivado por el hecho de haber asignado el ID del botón a la propiedad TargetControlID del ModalPopupExtender.
<asp:Button ID="btnEntrar" runat="server" Text="Entrar" Style="margin: 5px;" OnClick="btnEntrar_Click" />
....
....
<cc1:ModalPopupExtender ID="mpeMensaje" runat="server" TargetControlID="btnEntrar"
Como ya comentamos al comienzo de este artículo, lo deseable sería que el diálogo se mostrara solamente cuando los valores de los TextBox no cumplan la condición especificada en el code-behind asociado al botón. Para conseguirlo vamos a recurrir a un pequeño truco, consistente en asignar a la propiedad TargetControlID un control con el cual el usuario no pueda interaccionar, de manera que será nuestro code-behind quien controle cuándo visualizar el mensaje.
Primeramente añadiremos al formulario Web un control Label, que permanecerá oculto mediante la asignación del estilo "display: none".
<asp:Button ID="btnEntrar" runat="server" Text="Entrar" Style="margin: 5px;" OnClick="btnEntrar_Click" />
<asp:Label ID="lblOculto" runat="server" Text="Label" Style="display: none;" />
A continuación asignaremos este control a la propiedad TargetControlID.
<cc1:ModalPopupExtender ID="mpeMensaje" runat="server" TargetControlID="lblOculto"
....
Con esto conseguiremos que la pulsación del botón btnEntrar no sea la que produzca la apertura del cuadro de diálogo, ¡pero todavía necesitamos seguir abriéndolo!, aunque claro está, de forma controlada por nosotros, y para ello vamos a recurrir a un método del ModalPopupExtender cuyo nombre lo dice todo: Show.
Empleado desde el evento Click del control btnEntrar, el método Show abrirá el cuadro de mensaje solamente cuando los datos introducidos por el usuario no se ajusten a los especificados.
protected void btnEntrar_Click(object sender, EventArgs e)
{
// si los datos de acceso son correctos
// se muestra el literal que indica dicho estado
if (this.txtNombre.Text == "Elena" && this.txtClave.Text == "123")
{
this.lblAccesoPermitido.Visible = true;
}
else
{
// si los datos de acceso no son válidos
// mostrar el cuadro de mensaje
this.mpeMensaje.Show();
}
}
En la siguiente figura podemos observar nuestra caja de mensajes en plena ejecución.

Y ya para finalizar, queremos remarcar el hecho de haber utilizado el estilo "display: none" para ocultar el control lblOculto, en detrimento de la propiedad Visible a False, ya que en el caso de haber utilizado esta última opción, el efecto conseguido habría sido que el cuadro de mensaje no se hubiera visualizado, aun cuando se cumplieran las condiciones adecuadas para ello.
Esperando que os resulte de utilidad, el código fuente del ejemplo queda disponible en los siguientes enlaces: C# y VB.
Un saludo.