El código que aquí describo esta en C#, pero en el archivo adjunto se encuentran dos proyectos, uno en C# y el otro en VB.
Descargar ejemplo Calendario_PopUp.zip
En un pequeño trabajo hace un tiempo quise utilizar un control de Fechas, la idea era simple, escribir una fecha «válida» en una caja de Texto… pero despues de un rato me puse a pensar… los usuarios (benditos sean los ignorantes dijo alguien) suelen ingresan datos equivocados, así que habría que validar las cajas de textos… y recordé al Control DTPicker de nuestro querido amigo Visual Basic 6, pero no encontré algo parecido en los controles de .NET (al menos no para aplicaciones web, si alguien lo encuentra por favor saqueme de esta ignorancia). El punto es que hice un calendario que queda mas o menos como en esta figura:
public abstract class MiCalendario { private static string inicio = "<script language='JavaScript'>document.getElementById('"; private static string nombre = "').value = showModalDialog('Calendario.aspx'"; private static string atributos = "'dialogTop=100px; dialogLeft=250px; dialogWidth=206px; " + "dialogHeight=205px; center=yes; help=no; status=no; menubar=no; resizable=no; border=thin')"; public static void verCalendario(System.Web.UI.Page pagina, string control) { string wFecha = inicio + control + nombre + ",'', " + atributos + "</script>"; pagina.ClientScript.RegisterStartupScript(pagina.GetType(), "ventana", wFecha); } public static void verCalendario(System.Web.UI.Page pagina, string control, string _default) { string wFecha = inicio + control + nombre + ", '" + _default + "', " + atributos + "</script>"; pagina.ClientScript.RegisterStartupScript(pagina.GetType(), "ventana", wFecha); } }
Se trata de una Clase Abstracta, con métodos estáticos, pues la idea es escribir la menor cantidad posible de código cada vez que se llame al calendario. Ahora, aclaremos algunos puntos de este código.
Tenemos dos métodos que tienen el mismo nombre, pero los diferencian sus parámetros (eso se llama sobrecarga según entiendo), en el primer caso, si al cargar el calendario, se cierra la ventana sin haber seleccionado alguna fecha, la ventana devolverá una cadena vacía. En el segundo caso, si el usuario cierra el calendario sin haber seleccionado alguna fecha, se devolverá la fecha que le hayamos indicado por defecto.
Ahora, estoy utilizando secuencias de comando de JavaScript para abrir la ventana emergente; para poder ejecutar alguna instrucción de JavaScript dentro de alguna clase de .NET debemos hacerlo por medio de ClientScript.RegisterStartupScript, esta instrucción requiere tres parámetros: el tipo de secuencia de comandos a utilizar, una clave que identifique a la secuencia y el texto de la secuencia que se registrará; anteponemos pagina para indicarle que se hace referencia a la página que invocó al calendario.
Además de esto, uso la intrucción ShowModalDialog de JavaScript, la cual me permite abrir una ventana modal (osea que no deja trabajar con la página que la invocó hasta que se cierre la ventana modal) y recuperar un valor de la página.
El primer parámetro hace referencia a la página que invocará a nuestro calendario, el segundo parámetro hará referencia al nombre de la Caja de Texto que deberá recibir el valor seleccionado en el Calendario y el tercero el valor por defecto que tendrá el calendario.
Una vez hecho esto crearemos la página web que contendrá el calendario… llamémosle Calendario.aspx, en dicha página dibujaremos un Control Calendario llamado cal, y una caja de texto llamada txtFecha.
Ahora en el código de la página web (NO en el codebehind, sino en el código HTML de la página) escribiremos lo siguiente, exactamente despues de la etiqueta <TITLE>, es decir dentro del <HEAD>:
<script type="text/javascript" language="javascript"> function retornaValor(){ if(document.getElementById('txtFecha').value == "") { if(dialogArguments == "") returnValue = ""; else returnValue = dialogArguments; } } </script> <base target="_self" />
Este JavaScript es para devolver el valor de la fecha seleccionada a la página que invocó la ventana emergente. Ahora modifiquemos la etiqueta body para que se vea de la siguiente manera: <body onunload=»retornaValor();»> y luego modifiquemos la etiqueta div para que se vea como sigue: <div style=»position:absolute; top:0; left:0;»>.
Ahora debemos escribir el siguiente código en el CodeBehind de nuestra página Calendario, osea en Calendario.aspx.cs, y debe quedar como se muestra a continuación:
using System; using System.Web.UI.WebControls; public partial class Calendario : System.Web.UI.Page { protected void cal_SelectionChanged(object sender, EventArgs e) { txtFecha.Text = cal.SelectedDate.ToShortDateString(); string devuelveFecha = "<script language='JavaScript'>" + "returnValue = document.getElementById('txtFecha').value;" + "close();</script>"; ClientScript.RegisterStartupScript(this.GetType(), "Devolver", devuelveFecha); } }
A buen entendedor, pocas palabras, pero por siacaso, al seleccionar una fecha en el control calendario escribimos la fecha en la caja de texto de la página Calendario, luego, como va a ocurrir un PostBack, la página se tendrá que descargar (evento onload del modelo de objetos del navegador), en ese momento le indicamos a la página que retorne el valor de la caja de texto y finalmente le decimos que se cierre la página del calendario.
Ahora ya esta todo listo… solo nos queda invocar el calendario y probar si funciona, de repente les estoy mintiendo y Uds. ni cuenta se dan… para probar la aplicación solo hace falta agregar un control TextBox y dos Controles Button, al TextBox le pondremos el nombre txtFecha. Ahora escribiremos en el primer botón el siguiente código
y en el segundo botón lo siguiente:
en este segundo caso, si hay una fecha escrita en la caja de texto y no se selecciona una fecha en el calendario entonces se devolverá la fecha que tenía el cuadro de texto.
Uds. pueden utilizar el método que deseen, no es obligatorio que usen ambos, y lo bueno de esto es que apenas deben escribir una línea de código. Probablemente el código aquí mostrado funcione mejor si usamos AJAX (ya que esta de moda) pero por lo pronto no lo he podido probar… pero creo que Uds. lo pueden hacer por mi y me avisan.
Espero que lo revisen y les sea de utilidad… nos vemos.