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» />
&nbsp;&nbsp;
<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.

20 Comentarios

  1. anonymous

    Lo que es importante en el MessageBox es que es dinámico, uno puede mostrar cualquier mensaje al usuario.
    He estado tratando de modificar el código acá para poder mostrar cualquier mensaje al usuario pero no he podido realizarlo.
    Alguien ha hecho algo parecido?

  2. lmblanco

    Hola Jairo

    Pues utilizando el mismo código del ejemplo, en el evento del botón que muestra el ModalPopupExtender, justo antes de mostrar el panel conteniendo el mensaje, podemos acceder a los controles Label que contienen el título y el texto del mensaje, y cambiarlos por otros valores diferentes de los originales; algo parecido a lo 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;
    }
    else
    {
    // si los datos de acceso no son válidos
    // mostrar el cuadro de mensaje
    DateTime dtFecha = DateTime.Today;
    this.Label5.Text = «Aviso » + dtFecha.ToString(«dddd»);
    this.Label7.Text = «Un mensaje distinto «+ dtFecha.ToString(«dd-MMMM»);
    this.mpeMensaje.Show();
    }
    }
    //————————————–

    Un saludo.
    Luismi

  3. anonymous

    No pude hacer lo que dice el codigo anterior, a ver si alguien me puede ayudar y poder mostrar diferentes errores en el label.

    Saludos

  4. anonymous

    De buen nivel tu articulo, pero como no podria ser de otra manera yo tambien tengo una pregunta respecto al ModalPopupExtender, lo que pasa es que tengo un formulario para administracion de usuarios, y tengo un campo de contraseña, lo que necesito es confirmar esta contraseña para la cual utilizo el ModalPopupExtender, el problema que he encontrado es que desde el codebehind no he encontrado la forma que me regrese si las constraseñas son iguales o no? quiza no se pueda o si conces la solucion, me seria de gran ayuda, gracias

  5. lmblanco

    Hola Marco

    Gracias por tu opinión, en cuanto al problema que planteas, supongamos que hemos creado un panel para abrir como un ModalPopupExtender con el siguiente código:

    //——————————————-


      


    //——————————————-

    Al pulsar el botón aceptar del modalpopup ejecutamos el siguiente código en javascript asociado a dicho botón, en el cual enviamos el formulario al servidor:

    //——————————————-

    //——————————————-

    De esta forma, desde codebehind podríamos recuperar los valores de los textbox que hemos situado en el modalpopup:

    //——————————————-
    protected void Page_Load(object sender, EventArgs e)
    {
    if (this.IsPostBack)
    {
    string sPassw1 = this.txtPwd1.Text;
    string sPassw2 = this.txtPwd2.Text;
    // comprobaciones de igualdad
    //….
    }
    }
    //——————————————-

    Espero que con algunos ajustes pueda servirte.

    Un saludo.
    Luismi

  6. anonymous

    Excelente, si en efecto, lo he probado y resulto de maravilla, partiendo de lo que planteas hice los arreglos necesarios para que se adaptara a mi formulario y lo que a mí me hacia falta es el window.form1.submit();, eso no lo conocia, excelente, muchas gracias

  7. lmblanco

    Hola Marco

    Estupendo, me alegra mucho que te haya servido de ayuda.

    Un saludo.
    Luismi

  8. anonymous

    muy bueno tu código, me sirvió muchisimo.
    genial el paso a paso.
    ahora, tengo un problema…me da un error cuando lo uso.Me larga el msg.:
    «The control ‘lblOculto’ already has a data item registered.
    Nombre del parámetro: control»
    en determinados casos, y no encuentro el problema
    se agradece cualquier colaboración

  9. lmblanco

    Hola La Maga

    Gracias por leer el post. Respecto al error que me comentas yo no lo he experimentado, pero quizá pudiera deberse a la versión del Ajax Toolkit que estás utilizando.

    Por lo que se indica en el siguiente enlace parece ser un error con el que también se han encontrado otras personas:

    http://www.codeplex.com/AjaxControlToolkit/WorkItem/View.aspx?WorkItemId=7115

    Si no tienes la versión más reciente del Toolkit, prueba a descargarla e instalarla, a ver si con ello consiguieras que no el error no volviera a aparecer. En el siguiente enlace tienes la descarga de la última versión:

    http://www.codeplex.com/AjaxControlToolkit/Release/ProjectReleases.aspx?ReleaseId=16488

    Un saludo.
    Luismi

  10. anonymous

    Muy bien el ejemplo doc de verdad te pasestes chvr!!! TE AMO!!!

  11. anonymous

    hola necesito ayuda lo que sucede es que estoy iniciando en es to y necesito de tu ayuda por favor
    lo que tengo es un formulario con varios textbox
    y dos combobox y un boton enviar lo que necesito es q cuando se alla enviado correctamente muestre un mensaje utilizando el modalpopupextender q diga elementos enviados correctamente si me puede ayudar por favor
    estoy utilizando visual studio 2008 c#

  12. anonymous

    Excelente post, la solución exacta a mi problema.

    En caso de que necesiten usar tb requiredfieldvalidator o cualquier otro validador mi solución propuesta es:
    en la clase crear una variable tipo bool

    bool correcto = false;

    en el load de la pagina usar

    protected void Page_Load(object sender, EventArgs e)

    {
    if(IsPostBack)
    {
    correcto=true;
    }


    }
    y en el botón Entrar poner

    protected void btnEntrar_Click(object sender, EventArgs e)
    {

    if(correcto)
    {
    this.mpeMensaje.Show();
    }

    }

    Para Felipe, lo que pongo yo en este mensaje más arriba, puedes usar

    protected void btnEntrar_Click(object sender, EventArgs e)
    {

    //Aquí la validación de los datos enviados correctamente
    bool enviado = true;

    if(correcto&&enviado)
    {
    this.mpeMensaje.Show();
    }else
    {
    this.mpeMensaje2.Show();
    }

    }

    Donde mpeMensaje2 es un ModalPopUpExtender para otro panel que dice no se enviaron los datos correctamente

    Saludos

  13. lmblanco

    Hola Juan

    Muchas gracias por tu interés en el post y por tu ayuda en aportar la solución para Felipe 😎

    Un saludo.
    Luismi

  14. anonymous

    Mira tengo ese mismo ModalPopupExtender y dentro pongo un Combobox de ajaxcontroltoolkit. y no se que pasa que no se muestra correctamente el combobox.
    sabes como solucionarlo?

  15. lmblanco

    Hola Daniel

    Yo he utilizado el siguiente código fuente para poner un desplegable dentro del ModalPopupExtender y sí que se muestra el desplegable, a falta de hacer algunos ajustes, pero se visualiza.

    //—————————————-


      












    //—————————————-

    Un saludo.
    Luismi

  16. anonymous

    SALUDOS
    YO LO HE PROBADO DENTRO DE UN MASTER PAGE PERO AL MOMENTO DE QUE SALGA EL PANEL EN MEDIO DE LA PAGINA ME SALE ABAJO DE MI PAGINA WEB Y ATRAS DE LA PANTALLA GRIS, ALGO QUE PUEDA MODIFICAR O UNA PROPIEDAD QUE TENGA QUE AGREGAR, GRACIAS.

  17. lmblanco

    Hola Julio

    Revisa en tu página máster y en el webform las etiquetas ContentPlaceHolder y Content respectivamente para comprobar que los controles están bien ubicados. Por ejemplo, en una página máster podrías tener un código parecido al siguiente:

    //———————————————-
    < %@ Master Language="C#" AutoEventWireup="true" CodeBehind="Maestra01.master.cs" Inherits="CuadroMensajeModalPopup_CS.Maestra01" %>

    < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


    Cajas de mensaje con ModalPopupExtender




    CABECERA PAGINA MAESTRA


    PIE PAGINA MAESTRA



    //———————————————-

    Mientras que en el webform la situación del código dentro de las etiquetas de contenido podría ser similar a la siguiente:

    //———————————————-

    < %@ Page Title="" Language="C#" MasterPageFile="~/Maestra01.Master" AutoEventWireup="true" CodeBehind="PagDefault2.aspx.cs" Inherits="CuadroMensajeModalPopup_CS.PagDefault2" %>

    < %@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>




    //….
    //….


    //———————————————-

    Espero que te sirva de ayuda.

    Un saludo.
    Luismi

  18. anonymous

    Gracias por tu codigo muy bueno, apenas me estoy iniciando en esta onda del AJAX y fijate. ke no puedo hacerlo funcionar el problema es ke no me aparece nada… la pagina no me marca error ni nada de anda… no se algun tip.. no se si sea de configuracion o ke tenga ke hacer. lo unico ke hace es al dar aceptar. solo envia un postback y es todo lo ke hace… gracias

  19. anonymous

    Ya lo pude hacer funcionar.. resulta ke necesitaba instalar el framework 4 y con eso funciono … tenia en la configuracion del IIS la version 3.5 y no hacia nada. .:S pero instale el 4 y funciono a la perfeccion gracias…

  20. lmblanco

    Hola Ricardo

    Gracias por tu interés en el artículo, y me alegro de que finalmente te funcionara el ejemplo.

    Un saludo,
    Luismi

Responder a Cancelar respuesta

Tema creado por Anders Norén