IntroducciónA
menudo resulta útil mostrar mensajes de "espere" o imágenes gif animadas durante el proceso de envío del formulario de una aplicación web, especialmente cuando el proceso de envío lleva mucho tiempo. Recientemente desarrollé un programa de envío de encuestas donde los usuarios internos cargan hojas de cálculo de Excel a través de una página web. El programa inserta los datos de la hoja de cálculo cargados en la base de datos. Este proceso solo toma unos segundos, pero incluso si son unos segundos, es un proceso de espera muy obvio desde la perspectiva de la página web. Durante las pruebas del programa, algunos usuarios hicieron clic repetidamente en el botón de carga. Por lo tanto, es útil proporcionar un mensaje visual para informar a las personas que la carga está en progreso. Y oculte el botón de carga al mismo tiempo para evitar clics múltiples. El control presentado aquí es una subclase del control Botón, que demuestra cómo encapsular código JavaScript del lado del cliente en un control de servidor ASP.NET para proporcionar funciones convenientes.
Aunque existen muchos ejemplos de JavaScript para lograr esto, encontré algunos problemas cuando intenté encapsular estas funciones en controles ASP.NET. Primero intenté invalidar el botón a través del controlador onclick de JavaScript y reemplazarlo con otro texto. Pero lo encontré muy complicado, ya que esto obstaculizará la función del evento de clic en el lado del servidor asp.net. Lo que finalmente funcionó y tuvo buen soporte para diferentes navegadores fue representar el botón en una etiqueta div. El div se puede ocultar y apartar del evento de clic de asp.net.
Uso del control
Como derivado del control de botón normal, las funciones de PleaseWaitButton son básicamente las mismas. Utiliza tres propiedades adicionales para administrar la visualización de mensajes o imágenes de tipo "Espere" cuando se hace clic en el botón.
Por favor espere texto
Este es el mensaje de texto del lado del cliente que se muestra y, si está presente, reemplazará el botón cuando se haga clic en él.
Por favor espereImagen
Este es el archivo de imagen (como una imagen gif animada) que se muestra y, si está presente, reemplazará el botón cuando se haga clic en él. Este atributo se convertirá en el atributo src en la etiqueta <img>.
Por favor, espere, escriba
Uno de los valores de enumeración PleaseWaitTypeEnum: TextOnly, ImageOnly, TextThenImage o ImageThenText. Controla el diseño de mensajes e imágenes.
A continuación se muestra un archivo .aspx de ejemplo que muestra un PleastWaitButton con los conjuntos PleaseWaitText y PleaseWaitImage.
<%@ Idioma de la página="C#" %>
<%@ Registrar TagPrefix="cc1" Namespace="JavaScriptControls"
Asamblea="Por favorWaitButton" %>
<script runat="servidor">
vacío privado PleaseWaitButton1_Click (remitente del objeto, System.EventArgs e)
{
// Controlador de eventos Click del lado del servidor;
// simula algo que podría llevar mucho tiempo,
// como la carga de un archivo o el procesamiento del servidor que requiere mucho tiempo
Fecha y hora dt = Fecha y hora.Now.AddSeconds(5);
mientras (FechaHora.Ahora <dt)
{
// no hacer nada; simular una pausa de 5 segundos
}
// al final del ciclo muestra un mensaje de éxito
// y ocultar el formulario de envío
panelSuccess.Visible = verdadero;
PleaseWaitButton1.Visible = falso;
}
</script>
<html>
<cabeza>
<title>Probando el botón Espere</title>
</cabeza>
<cuerpo>
<id de formulario="Form1" método="publicación" runat="servidor">
<P>Probando el control PleaseWaitButton.</p>
<cc1:Por favorBotón de espera id="Por favorBotón de espera1" runat="servidor"
Text="Haz clic en mí para iniciar un proceso que requiere mucho tiempo"
PleaseWaitText="Espere por favor"
PleaseWaitImage="por favorEspera.gif"
OnClick="Por favor, espereButton1_Click" />
<asp:Panel id="panelSuccess" runat="servidor"
visible="falso">
Gracias por enviar este formulario. Realmente lo eres.
el usuario más genial al que he tenido el placer de servir.
No, de verdad, lo digo en serio. Ha habido otros, claro.
pero realmente estás en una clase por ti mismo.
</asp:Panel>
</formulario>
</cuerpo>
</html>
Cómo funciona
El control PleaseWaitButton representa un botón ASP.NET estándar dentro de una etiqueta <div>. También muestra una etiqueta <div> vacía para la información/imagen. Cuando se hace clic en el botón, la función Javascript controla la ocultación del botón y la visualización de la información (consulte la función del cliente a continuación). Para mayor comodidad, la implementación de todo el código de cliente javascript necesario se maneja mediante el control del servidor PleaseWaitButton.
Dado que PleaseWaitButton implementa su propio controlador onclick de JavaScript, debemos tomar algunos pasos adicionales para preservar el controlador onclick original y permitir que el control ejecute limpiamente algún código de validación del lado del cliente. Para lograr este objetivo, primero restauramos la clase base Button en un búfer de cadena y luego la manejamos hábilmente para incluir el código onclick que definimos.
Anulación protegida Renderizado vacío (salida HtmlTextWriter)
{
// Genera el html del botón (con atributos)
// a un HtmlTextWriter ficticio
StringWriter sw = nuevo StringWriter();
HtmlTextWriter wr = nuevo HtmlTextWriter(sw);
base.Render(wr);
cadena sButtonHtml = sw.ToString();
wr.Cerrar();
sw.Cerrar();
// ahora modifica el código para incluir un controlador "onclick"
// con nuestra función PleaseWait() llamada apropiadamente
// después de cualquier validación del lado del cliente.
sButtonHtml = ModificarJavaScriptOnClick(sButtonHtml);
// antes de renderizar el botón, genera un <div> vacío
// que se completará en el lado del cliente mediante javascript
// con un mensaje "por favor espere""
salida.Write(string.Format("<div id='pleaseWaitButtonDiv2_{0}'>",
this.ClientID));
output.Write("</div>");
// renderiza el botón en una etiqueta <div> encapsulada propia
salida.Write(string.Format("<div id='pleaseWaitButtonDiv_{0}'>",
this.ClientID));
salida.Write(sButtonHtml);
salida.Write("</div>");
}
Esta técnica de reducir el botón a un búfer de cadena y luego procesar su contenido al hacer clic es ciertamente un truco, pero nos permite implementar un código de validación estándar en la clase del botón principal y luego implementar nuestra llamada a la función Javascript PleaseWait(). Sin hacer esto, tendríamos que implementar nuestra llamada a la función PleaseWait() en el atributo onclick antes del código de validación, a menos que estuviéramos dispuestos a anular por completo la representación del atributo de la clase Button principal. De esta forma, incluso si hay errores de entrada en la página, tendrá el efecto de ocultar el botón y mostrar el mensaje "por favor espere" que no queremos. Por lo tanto, debemos forzar que la función PleaseWait() de nuestro cliente en el controlador onclick aparezca después de la validación de la página del cliente.
La modificación del atributo onclick ocurre en la función ModifyJavaScriptOnClick(). Esta función obtiene la cadena HTML representada por el botón y verifica si el atributo onclick está presente. Si es así, esta función comprueba si se utiliza el código de validación del lado del cliente. Si este es el caso, la función PleaseWait() que definimos se agregará al final del código onclick existente, inmediatamente después de la variable boolin Page_IsValid verificada por el cliente. Esta variable representa si se utiliza el control de validación. Si el valor de Page_IsValid es falso, no se mostrará el mensaje "Espere". Se muestra si es Verdadero.
cadena privada ModifyJavaScriptOnClick (cadena sHtml)
{
// Gracias al miembro de CodeProject KJELLSJ (Kjell-Sverre Jerijaervi)
// para obtener ideas de código para permitir que el botón funcione con
la cadena de validación del lado del cliente sReturn = "";
string sWhyWaitCode = GenerateWhyWaitJavascript();
// ¿existe un atributo onclick?
Regex rOnclick = new Regex("onclick="(?<onclick>[^"]*)");
Coincidir mOnclick = rOnclick.Match(sHtml);
si (mOnclick.Éxito)
{
// existe un atributo onclick;
// agrega nuestro código al final si es del lado del cliente;
// se ha realizado la validación, asegúrese
// comprobamos si la página es válida;
string sExisting = mOnclick.Groups["onclick"].Valor;
cadena sReplace = sExistente
+ (sExisting.Trim().EndsWith(";") ? "" : "; ");
si (IsValidatorIncludeScript() && this.CausesValidation)
{
// incluye código para comprobar si la página es válida
cadena sCode = "if (Page_IsValid) " + sPor favorWaitCode
+ "retorno Page_IsValid;";
// agrega nuestro código al final del código onclick existente;
sReemplazar = sReemplazar + sCódigo;
}
demás
{
// no te preocupes si la página es válida;
sReemplazar = sReemplazar + sPor favorEspereCode;
}
// ahora sustituye nuestro código onclick
sReplace = "onclick="" + sReplace;
sReturn = rOnclick.Replace(sHtml, sReplace);
}
demás
{
// no existe ningún atributo onclick;
// agrega el nuestro
int i = sHtml.Trim().Longitud - 2;
string sInsert = " onclick="" + sPor favorWaitCode + "" ";
sReturn = sHtml.Insert(i, sInsert);
}
return sReturn;
}
IsValidatorIncludeScript() utiliza la verificación anterior para ver si hay un bloque de código Javascript estándar para el control de validación de asp.net registrado con la página. A continuación se utiliza un método simple para probar si hay un código de validación y variables como Page_IsValid.
bool privado IsValidatorIncludeScript()
{
// devuelve VERDADERO si esta página tiene javascript registrado
// para la validación del lado del cliente; este código no puede estar registrado;
// si ASP.NET detecta lo que piensa (correcta o incorrectamente)
// es un navegador de nivel inferior
return this.Page.IsStartupScriptRegistered("ValidatorIncludeScript");
} Lo siguiente GenerateWhyWaitJavascript() construye la función Javascript PleaseWait() contenida en el atributo onclick. Podemos determinar el diseño deseado inspeccionando las propiedades del control.
cadena privada GenerateWhyWaitJavascript()
{
// crear una llamada a la función JavaScript "Por favorWait()"
// adecuado para su uso en un controlador de eventos onclick
string sMessage = "";
cadena sText = _pleaseWaitText;
cadena sImage = (_pleaseWaitImage! = String.Empty
? cadena.Formato(
"<img src="{0}" align="absmiddle" alt="{1}"/>"
, _por favorEspereImagen, _por favorEspereTexto )
: String.Empty);
// establece el diseño basado en PleaseWaitType
cambiar (_por favorWaitType)
{
caso PleaseWaitTypeEnum.TextThenImage:
sMensaje = sTexto + sImagen;
romper;
caso PleaseWaitTypeEnum.ImageThenText:
sMensaje = sImagen + sTexto;
romper;
caso PleaseWaitTypeEnum.TextOnly:
sMensaje = sTexto;
romper;
caso PleaseWaitTypeEnum.ImageOnly:
sMensaje = sImagen;
romper;
}
// devuelve el fragmento de código final
cadena sCode = cadena.Formato(
"Por favor, espere ('por favorWaitButtonDiv_ {0}',
'por favorWaitButtonDiv2_{1}', '{2}');"
, este.ClientID, este.ClientID, sMessage);
sCode = sCode.Replace(""", """);
devuelve sCode;
}
Si especifica PleaseWaitImage, debe incluir un fragmento adicional de código Javascript para notificar al cliente que precargue la imagen. El registro de este script debería aparecer en el método OnPreRender anulado. La clave registrada es el nombre de la imagen; si varios botones usan la misma imagen, el script de precarga solo debe implementarse una vez. Aquí se utiliza una expresión regular para crear una variable de imagen Javascript para garantizar que los caracteres especiales (como barras en las rutas de los archivos) se conviertan en guiones bajos.
anulación protegida anular OnPreRender (EventArgs e)
{
base.OnPreRender (e);
// Si estamos usando una imagen, registra algo de javascript
// para la precarga de imágenes del lado del cliente
si (_pleaseWaitImage! = String.Empty
&& _pleaseWaitType! = PleaseWaitTypeEnum.TextOnly)
RegistrarJavascriptPreloadImage(_pleaseWaitImage);
}
registro vacío privadoJavascriptPreloadImage(cadena sImage)
{
Regex rex = new Regex("[^a-zA-Z0-9]");
cadena sImgName = "img_" + rex.Replace(sImage, "_");
StringBuilder sb = nuevo StringBuilder();
sb.Append("<lenguaje de escritura='JavaScript'>");
sb.Append("if (document.images) { ");
sb.AppendFormat("{0} = nueva imagen();", sImgName);
sb.AppendFormat("{0}.src = "{1}";", sImgName, sImage);
sb.Append(" } ");
sb.Append("</script>");
this.Page.RegisterClientScriptBlock(sImgName + "_PreloadScript",
sb.ToString());
}
Funciones del lado del cliente
El archivo de texto incrustado javascript.txt contiene el <div> que oculta el botón y el código del lado del cliente que muestra el mensaje o imagen "espere". Estos códigos se cargan en el método privado RegisterJavascriptFromResource() llamado en el método OnInit() anulado. Este método llama al método genérico GetEmbeddedTextFile(), que carga el archivo como fuente y devuelve el contenido como una cadena.
anulación protegida anulación OnInit (EventArgs e)
{
base.OnInit(e);
// se mantiene el código javascript del lado del cliente
// en un recurso incrustado; cargar el script
// y registrarlo en la página.
RegistrarseJavascriptFromResource();
}
Registro vacío privadoJavascriptFromResource()
{
// carga el archivo de texto incrustado "javascript.txt"
// y registrar su contenido como script del lado del cliente
cadena sScript = GetEmbeddedTextFile("javascript.txt");
this.Page.RegisterClientScriptBlock("Por favorWaitButtonScript", sScript);
}
cadena privada GetEmbeddedTextFile (cadena sTextFile)
{
// función genérica para recuperar el contenido
// de un recurso de archivo de texto incrustado como una cadena
// obtendremos el ensamblado en ejecución y lo derivaremos
// el espacio de nombres usando el primer tipo en el ensamblado
Ensamblaje a = Ensamblaje.GetExecutingAssembly();
String sNamespace = a.GetTypes()[0].Namespace;
// con el ensamblado y el espacio de nombres, obtendremos el
//recurso incrustado como una secuencia
Corriente s = a.GetManifestResourceStream(
string.Format("{0}.{1}", sNamespace, sTextFile)
);
// lee el contenido de la secuencia en una cadena
StreamReader sr = nuevos StreamReader(s);
Cadena sContents = sr.ReadToEnd();
sr.Close();
s.Close();
devolver sContenidos;
}
El recurso incrustado javascript.txt contiene el método del lado del cliente PleaseWait() que se ejecuta en el controlador Javascript onclick del botón. Este código también llama a un método del lado del cliente HideDiv() para ocultar el contenedor del botón <div> y luego reúne la información o imagen en la etiqueta <div> previamente vacía configurando el atributo internalHTML. La función auxiliar GetDiv() devuelve un objeto <div> con id comprobando document.getElementById, document.all y document.layers, asegurando la compatibilidad con diferentes navegadores. A continuación se muestra el código completo de javascript.txt:
<lenguaje de escritura="JavaScript">
función ObtenerDiv(sDiv)
{
vardiv;
si (document.getElementById)
div = documento.getElementById(sDiv);
si no (documento.todo)
div = eval("ventana." + sDiv);
de lo contrario si (documento.capas)
div = documento.capas[sDiv];
demás
div = nulo;
devolver div;
}
función OcultarDiv(sDiv)
{
d = ObtenerDiv(sDiv);
si(d)
{
if (document.layers) d.visibilidad = "ocultar";
else d.style.visibility = "oculto";
}
}
función PleaseWait(sDivButton, sDivMessage, sInnerHtml)
{
OcultarDiv(sDivButton);
var d = GetDiv(sDivMessage);
si (d) d.innerHTML = sInnerHtml;
}
</script>
Enlace original: http://www.codeproject.com/aspnet/ PleaseWaitButton.asp
Descargar Proyecto Fuente - 7 Kb
Descargar proyecto de demostración - 30 Kb
http://www.cnblogs.com/jeffamy/archive/2006/08/20/481952.html