PopUp o Ventanas Modales en ASP.NET

ENERO 2016
PROBALO EN MVC CAMPEON!

Muchas veces porque queda muy agradable a la vista, es conveniente abrir una ventana (popup) con información adicional sobre un ítem deseado. Otro caso (particularmente el que me tocó desarrollar) puede ser hacer una especie de Wizard donde las ventanas cumplan una suerte de varios pasos donde se pueda ir para atrás,adelante y/o finalizar, al mejor estilo instalación de cualquier soft (siguiente,siguiente,siguiente,instalar…finalizar).

Lo que voy a mostrar parte de una página Principal (Página Madre) que es la que va a abrir el popup y acá se pueden usar 2 maneras, una ventana modal o una ventana modeless.

ventana modal: Este tipo de ventanas no permite la interacción con la ventana anterior mientras este abierta, de hecho interrumpe cualquier ejecución que se este haciendo por atrás. Por ejemplo si nosotros hacemos un postback y en el servidor abrimos una ventana con el método de JS window.showModalDialog puede ocurrir que la página madre quede en blanco o a medio cargar.

ventana modeless: Estas ventanas si permiten la interacción con su ventana madre, de hecho es posible hacer click en la ventana de atrás y lo va a permitir. Por lo comentado arriba este tipo modal puede ser útil. Pero si por ejemplo vamos a abrir una modal de una fila en un gridview que tiene un enlace a eliminarlo, si lo hace mientras esta la modeles abierta se lo va a permitir.

Este ejemplo esta diseñado para IE 6.0 en adelante y voy a usar VS2005. Básicamente voy a hacer esto:

Voy a usar una sola página como Wizard pero pueden ser las que se necesiten, al fin y al cabo todas terminan en un página de Fin.

La página principal va a contar con script porque va a mantener una variable para poder tomarla al final:

<script>
var Guardar;
function DeseaGuardar()
{
window.document.Form1.txtOculto.value=Guardar;
__doPostBack('lnkGuardar','');
}
function Ejecutar()
{
//Agregamos el JS para pasar el parametro</span>
var param='';
param='valor=' + window.document.Form1.TextBox1.value;
WizardGeneral(200,550,'Default2.aspx',param);
}
</script>

La función WizardGeneral está en un JS que adjunto con todo el proyecto al final y es la que arma la URL para abrir el Wizard de una manera u otra (Modal/Modeless) . Yo lo hago con una función en el evento onclick llamando a Ejecutar pero por ejemplo si queremos hacer popups de una grilla agregándole a todas las rows solo vamos a necesitar el ID de cada row para levantar los datos en el popup con lo cual se puede hacer todo en la 1era carga de la página agregando el id en el evento RowDatabound. Yo a modo de ejemplo solo modifico un textbox.

El HTML de la página sería algo así:

<HTML>
<HEAD>
<title>Prueba</title>
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
<meta content="Visual Basic .NET 7.1" name="CODE_LANGUAGE">
<meta content="JavaScript" name="vs_defaultClientScript">
<script language="javascript" src="JS/ScriptJS.js"></script>
</HEAD>
<body style="text-align: left">

<form id="Form1" method="post" runat="server">



<table width="100%">


<tr>


<td style="text-align: center;" colspan="3">
<asp:Label ID="lblerror" runat="server" Width="100%"></asp:Label></td>


</tr>




<tr>


<td style="width: 24px">
<asp:Label ID="Label1" runat="server" Text="Valor"></asp:Label></td>




<td style="width: 60px">
<asp:TextBox ID="TextBox1" runat="server" Width="279px"></asp:TextBox>
</td>




<td style="width: 100px">
</td>


</tr>




<tr>


<td style="width: 24px">
</td>




<td style="width: 60px; text-align: center;">
<input id="btnBoton" type="button" value="Popup" runat =server  /></td>




<td style="width: 100px">
</td>


</tr>


</table>



<asp:LinkButton ID="lnkGuardar" runat="server"></asp:LinkButton>amp;nbsp;
<input id="txtOculto" style="width: 54px" runat =server  type="hidden" />
</form>

</body>
</HTML>

Al final de la página hay 2 elementos importantes un Link, que es el que va a causar el postback de la página madre cuando termine el wizard y un hidden que es el que va a tener el valor de retorno del wizard. El código de servidor es mas o menos este:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Introducir aquí el código de usuario para inicializar la página
If Not Page.IsPostBack Then
Try
txtOculto.Value = ""
btnBoton.Attributes.Add("onclick", "javascript:Ejecutar()")
Catch ex As Exception
lblerror.Text = ex.Message
End Try
End If
End Sub

Protected Sub lnkGuardar_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles lnkGuardar.Click
'txtOculto tiene el valor modificado que me devuelve el Wizard
If Not String.IsNullOrEmpty(txtOculto.Value) Then TextBox1.Text = txtOculto.Value
End Sub

Cuando la página de fin se cierre «cargar» de nuevo esta página ósea va a pasar por el page_load por eso hay que manejar bien el page.ispostback para no pisar valores y luego va a entrar por el click del Link que nosotros le formamos a hacer con la instrucción de Javascript __doPostBack. La Página del Wizard tiene este HTML:

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Página del Wizard</title>
<base target="_self">
</head>
<body >
<script language="javascript">
          var sData = dialogArguments;

          sData.Guardar= '';
         sData.DeseaGuardar();
       function sourceCode()  //Para ver el codigo fuente
         {
          d=window.open();
          d.document.open('text/plain').write(document.documentElement.outerHTML);
          }

</script>
<form id="form1" runat="server" method="post">
<table>
<tr>
<td style="width: 100px">
<asp:Label ID="Label1″ runat="server" Text="Valor del Wizard" Width="118px"></asp:Label></td>
<td style="width: 100px">
<asp:TextBox ID="TextBox1″ runat="server"></asp:TextBox></td>
</tr>
<tr>
<td style="width: 100px"></td>
<td style="width: 100px">
<asp:Button ID="Button1″ runat="server" Text="Ejecutar" /></td>
</tr>
<tr>
<td colspan="2″>
<asp:Label ID="Label2″ runat="server" ForeColor="#0000C0″ Text="Al cambiar esta valor se modifica el textbox de la página principal"></asp:Label></td>
</tr>
</table>
</form>

</body>
</html>

Tiene algunas particularidades la primera es que tiene le atributo target= self esto es para cuando hacemos el response.redirect a la página de fin no nos abra una página sino que siga en la misma. Después la función Javascript toma el dialogArguments que son las variables o funciones de la página madre. Y por ultimo algo que nos puede ser muy útil para depurar es una función para ver el HTML de la página cuando se esta ejecutando, porque las modales no dejan hacer click derecho para ver el código. Simplemente se agrega el nombre (sourceCode) en el evento onload del Form y listo apenas carga la página tenemos una nueva ventanita con el HTML :D.

Este es el código de servidor:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Try
If Not Page.IsPostBack Then
TextBox1.Text = Request.Params("valor")
Else
Dim strpage As String = "General_Fin_W.aspx"
Dim paramFinal As String = "modo=modificacionamp;datos=".ToString + TextBox1.Text
strpage += "?".ToString + paramFinal.ToString 'General_Fin_W.aspx?modo=modificacionamp;datos=
Response.Redirect(strpage)
End If
Catch ex As Exception
Response.Write(ex.Message)
End Try
End Sub

y por ultimo la página de Fin HTML y código de Servidor:

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title></title>
<script language="JavaScript" type="text/javascript">

       function CerrarWizard()
       {
        var sData = dialogArguments;
           //var datos= document.Form1.HiddenField1.value; // Esto vale lo que
          //termina concatenando en el wizard
          var datos= document.Form1.HiddenField1.value;
          sData.Guardar=datos;
          sData.DeseaGuardar();
          window.close();
          }

         function sourceCode()  //Para ver el codigo fuente
           {
           d=window.open();
           d.document.open('text/plain').write(document.documentElement.outerHTML);
           }

</script> </head> <body class="BodyNormal" onactivate ="CerrarWizard();">
<form id="Form1" runat="server" >
<div style="text-align: center" > <asp:Label ID="lblMensajes" runat="server" CssClass="labelmensaje" Width="98%">Cargando ...</asp:Label>
 <asp:HiddenField ID="HiddenField1" runat="server" /></div>
</form>

 </body> </html> 

Tiene una simple pantalla blanca con un mensaje cargando…. (pero la idea es que prácticamente no aparezca) porque como se ve en la funcion hace en onload le asigna el valor a sData.Guardar (osea el valor oculto de la página madre) y despues hace un window.close.


Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Select Case Request.Params("modo")
Case "modificacion"
If Not String.IsNullOrEmpty(Request.Params("datos")) Then
HiddenField1.Value = Request.Params("datos")
End If
End Select
End Sub

La idea es hacer una sola página de fin en caso de que necesitamos varios Wizard por ejemplo para cargar Personas o Productos, etc. Todas devuelven 1 dato por ejemplo si son Wizard de Alta podrían devolver el ID a la página Madre para poder levantarlo desde ahí.

Lo subí a medifire aqui.

ACTUALIZADO 18/1/2016:
GoogleDrive

Saludos.

25 comentarios sobre “PopUp o Ventanas Modales en ASP.NET

  1. Tengo un problema tengo con una pagina asp.net que tiene una grilla, esta es llenada desde un popup en donde selecciono de una grilla las filas que quiero que se carguen en la grilla de la pagina que lo invoco, las filas seleccionadas son almacenadas en una variable sesion, es decir que al seleccionar las filas de la grillas del popup y cerrar el popup los datos son almacenados en un varible sesion y en el load de la pagina principal se llama al metodo para cargar la grilla, esto funciona en desarrollo, realizo el debug y la grilla de la pagina principal se carga pero cuando realizo el publish, en IIS6, y corro el aplicativo la grilla de pagina principal no muetsra los datos sino hasta que le doy F5, no se que pueda estar sucediendo, porfavor si me podria ayudar con este tema.

  2. De la manera en que lo hago yo osea con esta sentencia:

    btnBoton.Attributes.Add(«onclick», «javascript:Ejecutar()»)

    el hiperlink tambien se puede usar basta con cambiarla, en el pageload, a :

    If Not Page.IsPostBack Then
    miHyperLink.Attributes.Add(«onclick», «javascript:Ejecutar()»)
    End if

    para que el hyperlink tenga la rutina de Javascript que abre la ventana.

    Saludos

  3. mira yo tengo un problema segun el ejemplo de arriba lo e tratado de modificar para que trabaje con 2 forms solamente,de la siguiente manera:
    -1 aspx que llame al popup
    -2 el popup que retone los datos.
    codigo Fuente :

    Página sin título

     

    var Guardar;
    function DeseaGuardar()
    {
    window.document.form1.txtOculto.value=Guardar;
    __doPostBack(‘Button1′,»);
    }

    function url()
    {
    // window.open(«Popup.aspx?USP=usp_get_Usuario»,
    //»»,»width=600,height=400,left = 50,position=relative»);
    //Popup.moveTo(400,100);
    var param=»;
    param=’valor=’ + window.document.form1.TextBox1.value;
    window.showModalDialog(«popup.aspx?»+param,window,»dialogHeight:50px; dialogWidth:70px;»);
    }

    ————————
    Defualt.aspx
    ———————–
    protected void Page_Load(object sender, EventArgs e)
    {
    if (Page.IsPostBack==false )
    {
    txtOculto.Value = «»;
    Button1.Attributes.Add(«onclick», «javascript:url()»);
    }
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
    if (!string.IsNullOrEmpty(txtOculto.Value) )
    {
    TextBox1.Text = txtOculto.Value;
    }
    }

    ———————————–
    popup codigo fuente
    ———————————–

    Página sin título

    var sData = dialogArguments;
    sData.Guardar= »;
    sData.DeseaGuardar();
    function CerrarWizard()
    {
    var sData = dialogArguments;
    var datos= document.form1.HiddenField1.value;
    sData.Guardar=datos;
    sData.DeseaGuardar();
    window.close();
    }

    ————————————-
    popup.aspx
    ————————————-
    protected void Page_Load(object sender, EventArgs e)
    {
    if (Page.IsPostBack == false)
    {
    TextBox1.Text = Request.QueryString[«valor»];
    }
    else {
    HiddenField1.Value = TextBox1.Text;
    Response.Redirect(«Default.aspx»);
    }

    —————————————————–
    —————————————————–

    El error es que no devuelve el valor cambiado!

    me sale error constantemente! bueno si alguien sabe la solucion espero respuesta x esta pagina o a mi correo
    spike14_11@hotmal.com

  4. Fijate en la pagina popup.aspx de redireccionar a la pagina de fin que explico al final. Esa es la que le vuelve a la pagina madre.

    en popup.aspx podes hacer asi:

    HiddenField1.Value = TextBox1.Text;
    Response.Redirect(”Fin.aspx?datos=” & HiddenField1.Value );

    y en la pagina de Fin.aspx tiene un HTML algo asi:

    function CerrarWizard()
    {
    var sData = dialogArguments;
    // Esto vale lo que
    //termina concatenando en el wizard
    var datos= document.Form1.HiddenField1.value;
    sData.Guardar=datos;
    sData.DeseaGuardar();
    window.close();
    }

    —————————————–

    Despues en el Fin.aspx.vb (o .cs):

    If Not String.IsNullOrEmpty(Request.Params(«datos»)) Then

    HiddenField1.Value = Request.Params(«datos»)

    end if

    ——————————–

    Algo así proba osea básicamente crear una pagina mas que no se va a ver porque solo recibe la ultima pagina del wizard y lo cierra enviando el parametro dato a la pagina madre.

    Saludos

  5. excelente muy buen tema, trate de bajar el archivo para poder reisarlo a ams detalle pero no sirve el enlace, me lopodrias mandar a mi correo por favor, te lo agradeceria mucho, me serviria bastante ya que soy nuevo en esto de los popup, por favor. mi correo es temocop@hotmail.com

      1. Wooow….a eso se le llama rapidez. Muchas thanks, si tengo alguna duda ya la planteare…. Muchas gracias de verdad.

  6. Buenos tardes,

    Mira te explico mi proyecto, tengo una pagina principal llamada default.aspx con un menu en javascript. Ese menu según la opción que marques la envia por el metodo post a una pàg. opc.aspx. Un ejemplo:

    Clico en Nuevo Usuario y me dirige ha opc.aspx?opc=1 y de alli que me dirige a la ventana modal nuevo_usuario.aspx

    También lo que pensado es hacer el paso directamente del default.aspx?opc=1 a nuevo_usuario.aspx. Que cuando haga el Ispostback coja la opción y con un select sepa k modal abrir….

    Uy k lioso….jeje….weno solo necesito hacer ejecutar el javascript desde el menu javascript que tengo.

  7. Al final ya he conseguido cojer las variables por post en el javascript. Pero aun no he conseguido saber como ejecutar tu script en el menu javascript.

  8. Nose si entendí bien, el tema es que yo cuando hice esto lo pense para que la pagina 1 sea la principal (a la que después volves).
    Se me ocurre que podes poner todo el codigo en default.aspx osea no es necesario que vayas al servidor con la variable opc=1 y despuesa lanzar a nuevo_usuario.aspx.

    en el evento onclick podes hacerlo directamente:
    onclick=»javascript:Ejecutar(‘nuevo_usuario.aspx’);»

    donde Ejecutar es:

    function Ejecutar(miPagina)
    {
    //Agregamos el JS para pasar el parametro
    var param=»;
    param=’valor=’ + window.document.Form1.TextBox1.value;
    WizardGeneral(200,550,miPagina,param);
    }

    Despues si tenes que hacer otro wizard solo tenes que reemplazar el parametro de Ejecutar:

    onclick=»javascript:Ejecutar(‘otra_pagina.aspx’);»
    onclick=»javascript:Ejecutar(‘reotra_pagina.aspx’);»

    y ahi disparas todos los wizard desde tu default.aspx donde esta el menu sin necesidad de ir al servidor.
    Incluso podes distinguir desde que popup venis mandandole el parametro adecuado para atraparlo en lnkGuardar

    como hago aca(este codigo va en la pagina madre del wizard osea en tu caso default.aspx):

    Protected Sub lnkGuardar_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles lnkGuardar.Click
    ‘txtOculto tiene el valor modificado que me devuelve el Wizard
    If Not String.IsNullOrEmpty(txtOculto.Value) Then TextBox1.Text = txtOculto.Value
    End Sub

    vos ahi podes hacer un select case para diferenciar en caso de que tengas varios.

    Saludos.

    1. Merci por la contestación ya tengo todo un poco mas montado, lo que sigo teniendo un problema con hacer un wizard de dos paginas.

      El default.aspx es la principal, entro en alta_demanda.aspx desde el menu y lo que necesito es que al darle al btn_aceptar este me guarde los datos en la bbdd y luego me dirija al alta_tarea.aspx que también es un formulario modal.

      Ahora mismo ya grabo en la bbdd pero no consigo hacer el salto a la web alta_tarea.aspx

      Perdon por mis boberias, pero es que soy bastante novato jeje y muchisimas gracias por la ayuda.

  9. Hola, Tengo un problema capaz puedan ayudarme a encontrar la respuesta,
    El tema es asi, Tengo un form principal.aspx con un boton que abre otro form cliente.aspx (MODAL, showModalDialog), este ultimo a su vez tiene otro boton que abre otro form telefonos (showModalDialog).
    El problema que tengo es que cuando abre el form telefonos se duplica el form cliente, o sea se vuelve a abrir este de cliente y en total tengo dos de cliente.
    No entiendo que es lo que estoy haciendo mal si las sentencias son las mismas en todos los casos de apertura, Espero alguno pueda darme alguna idea de lo que esta sucediendo.
    Gracias…

  10. Buenas tardes, me ha gustado el ejemplo y funciona excelente, quizá el único pero es que solo funciona en IE, pero esto es solo de jugar un poco con la función WizardGeneral (JS) que trae la ventana hija.

    saludos

    1. Si, lo se. Hasta donde probé hacerlo en Firefox me topaba con un tema de seguridad que no permite cerrar una ventana que no fue abierta por la pagina madre, osea yo hago esto.
      Pagina madre–> abre popup1–>popup2–>popup3–>popup_fin.
      como popup_fin no lo abrió Pagina madre no me deja cerrarlo. Cualquier cosa que creas que pueda funcionar avísame y veos si lo podemos hacer andar.

      Saludos.

  11. Hola me parece muy bueno todo, pero no puedo adaptarlo a mi proyecto ya que en mi aspx no puedo utilizar el form1 sino que un content ContentPlaceHolder de la pagina principal del proyecto
    donde en la cabecera aparece el logo del proyecto en todas las paginas, entonces el codigo jscrip no me reconoce el window.document.Form1 y ya no sé que colocar en su lugar, y si coloco el Form1 por codigo html al ejecutar el programa, dice que no se admite dos etiquetas Form de servidor. Que puedo hacer ¿?

Replica a johan Cancelar la respuesta