EinführungEs
ist oft nützlich, während des Formularübermittlungsprozesses einer Webanwendung „Bitte warten“-Meldungen oder animierte GIF-Bilder anzuzeigen, insbesondere wenn der Übermittlungsprozess lange dauert. Ich habe kürzlich ein Programm zur Einreichung von Umfragen entwickelt, bei dem interne Benutzer Excel-Tabellen über eine Webseite hochladen. Das Programm fügt die hochgeladenen Tabellendaten in die Datenbank ein. Dieser Vorgang dauert nur wenige Sekunden, aber selbst wenn er nur wenige Sekunden dauert, handelt es sich aus Sicht der Webseite um einen sehr offensichtlichen Wartevorgang. Während des Testens des Programms klickten einige Benutzer wiederholt auf die Schaltfläche zum Hochladen. Daher ist es sinnvoll, eine visuelle Nachricht bereitzustellen, um den Leuten mitzuteilen, dass der Upload läuft. Und blenden Sie gleichzeitig den Upload-Button aus, um Mehrfachklicks zu verhindern. Das hier vorgestellte Steuerelement ist eine Unterklasse des Button-Steuerelements, das zeigt, wie clientseitiger JavaScript-Code in ein ASP.NET-Serversteuerelement gekapselt wird, um praktische Funktionen bereitzustellen.
Obwohl es viele Javascript-Beispiele gibt, um dies zu erreichen, habe ich einige Probleme festgestellt, als ich versuchte, diese Funktionen in ASP.NET-Steuerelemente zu kapseln. Ich habe zunächst versucht, die Schaltfläche über den Javascript-OnClick-Handler ungültig zu machen und durch anderen Text zu ersetzen. Aber ich fand es sehr knifflig, da dadurch die Funktion des Click-Events auf der Seite des asp.net-Servers beeinträchtigt wird. Was schließlich funktionierte und eine gute Unterstützung für verschiedene Browser bot, war die Darstellung der Schaltfläche in einem div-Tag. Das Div kann ausgeblendet werden und dem Klickereignis von asp.net nicht im Weg stehen.
Verwenden des Steuerelements
Als Ableitung des normalen Tastensteuerelements sind die Funktionen von PleaseWaitButton im Wesentlichen gleich. Es verwendet drei zusätzliche Eigenschaften, um die Anzeige von „Bitte warten“-Nachrichten oder Bildern zu verwalten, wenn auf die Schaltfläche geklickt wird.
PleaseWaitText
Dies ist die clientseitige Textnachricht, die angezeigt wird und, falls vorhanden, die Schaltfläche ersetzt, wenn auf die Schaltfläche geklickt wird.
PleaseWaitImage
Dies ist die Bilddatei (z. B. ein animiertes GIF-Bild), die angezeigt wird und, falls vorhanden, die Schaltfläche ersetzt, wenn darauf geklickt wird. Dieses Attribut wird zum src-Attribut im <img>-Tag.
PleaseWaitType
Einer der PleaseWaitTypeEnum-Enumerationswerte: TextOnly, ImageOnly, TextThenImage oder ImageThenText. Es steuert das Layout von Nachrichten und Bildern.
Unten finden Sie eine Beispiel-.aspx-Datei, die einen PleastWaitButton mit den Sätzen „PleaseWaitText“ und „PleaseWaitImage“ demonstriert.
<%@ Seitensprache="C#" %>
<%@ Register TagPrefix="cc1" Namespace="JavaScriptControls"
Assembly="PleaseWaitButton" %>
<script runat="server">
private void PleaseWaitButton1_Click(object sender, System.EventArgs e)
{
// Serverseitiger Click-Event-Handler;
// etwas simulieren, das lange dauern könnte,
// wie ein Datei-Upload oder eine zeitaufwändige Serververarbeitung
DateTime dt = DateTime.Now.AddSeconds(5);
while (DateTime.Now < dt)
{
// nichts tun; eine 5-sekündige Pause simulieren
}
// am Ende der Schleife eine Erfolgsmeldung anzeigen
// und das Absendeformular ausblenden
panelSuccess.Visible = true;
PleaseWaitButton1.Visible = false;
}
</script>
<html>
<Kopf>
<title>Testen von PleaseWaitButton</title>
</head>
<Körper>
<form id="Form1" method="post" runat="server">
<P>Testen des PleaseWaitButton-Steuerelements.</p>
<cc1:PleaseWaitButton id="PleaseWaitButton1" runat="server"
Text="Klicken Sie auf mich, um einen zeitaufwändigen Vorgang zu starten"
PleaseWaitText="Bitte warten"
PleaseWaitImage="pleaseWait.gif"
OnClick="PleaseWaitButton1_Click" />
<asp:Panel id="panelSuccess" runat="server"
sichtbar="false">
Vielen Dank, dass Sie dieses Formular abgeschickt haben
Der coolste User, den ich je bedienen durfte.
Nein, wirklich, ich meine es ernst. Es gab sicher auch andere.
aber du bist wirklich eine Klasse für dich.
</asp:Panel>
</form>
</body>
</html>
So funktioniert es:
Das PleaseWaitButton-Steuerelement rendert eine Standard-ASP.NET-Schaltfläche innerhalb eines <div>-Tags. Außerdem wird ein leeres <div>-Tag für die Informationen/das Bild gerendert. Beim Anklicken der Schaltfläche wird das Ausblenden der Schaltfläche und die Anzeige von Informationen durch die Javascript-Funktion gesteuert (siehe Client-Funktion unten). Der Einfachheit halber wird die Implementierung des gesamten erforderlichen Javascript-Clientcodes vom PleaseWaitButton-Serversteuerelement übernommen.
Da PleaseWaitButton seinen eigenen Javascript-OnClick-Handler implementiert, müssen wir einige zusätzliche Schritte unternehmen, um den ursprünglichen OnClick-Handler beizubehalten und dem Steuerelement die saubere Ausführung einiger clientseitiger Validierungscodes zu ermöglichen. Um dieses Ziel zu erreichen, stellen wir zunächst die Button-Basisklasse in einem String-Puffer wieder her und gehen dann geschickt damit um, um den von uns definierten Onclick-Code einzuschließen.
protected override void Render(HtmlTextWriter-Ausgabe)
{
// Den HTML-Code der Schaltfläche ausgeben (mit Attributen)
// zu einem Dummy-HtmlTextWriter
StringWriter sw = new StringWriter();
HtmlTextWriter wr = new HtmlTextWriter(sw);
base.Render(wr);
string sButtonHtml = sw.ToString();
wr.Close();
sw.Close();
// Jetzt den Code so ändern, dass er einen „onclick“-Handler enthält
// mit unserer PleaseWait()-Funktion, die entsprechend aufgerufen wird
// nach jeder clientseitigen Validierung.
sButtonHtml = ModifyJavaScriptOnClick(sButtonHtml);
// Vor dem Rendern der Schaltfläche ein leeres <div> ausgeben
// das wird clientseitig über Javascript ausgefüllt
// mit einer „Bitte warten“-Meldung“
Output.Write(string.Format("<div id='pleaseWaitButtonDiv2_{0}'>",
this.ClientID));
Output.Write("</div>");
// die Schaltfläche in einem eigenen kapselnden <div>-Tag rendern
Output.Write(string.Format("<div id='pleaseWaitButtonDiv_{0}'>",
this.ClientID));
Ausgabe.Write(sButtonHtml);
Ausgabe.Write("</div>");
}
Diese Technik, die Schaltfläche auf einen String-Puffer zu reduzieren und dann ihren Onclick-Inhalt zu verarbeiten, ist sicherlich ein Hack. Sie ermöglicht uns jedoch, Standardvalidierungscode in der übergeordneten Schaltflächenklasse zu implementieren und dann unseren JavaScript-Funktionsaufruf PleaseWait() zu implementieren. Ohne dies müssten wir unseren Funktionsaufruf PleaseWait() im onclick-Attribut vor dem Validierungscode implementieren, es sei denn, wir wären bereit, die Darstellung des Attributs der übergeordneten Button-Klasse vollständig zu überschreiben. Selbst wenn auf der Seite Eingabefehler auftreten, wird auf diese Weise die Schaltfläche ausgeblendet und die Meldung „Bitte warten“ angezeigt, die wir nicht möchten. Daher müssen wir erzwingen, dass die Funktion „PleaseWait()“ unseres Clients im Onclick-Handler nach der Validierung der Clientseite angezeigt wird.
Die Änderung des onclick-Attributs erfolgt in der Funktion ModifyJavaScriptOnClick(). Diese Funktion ruft den von der Schaltfläche gerenderten HTML-String ab und prüft, ob das onclick-Attribut vorhanden ist. Wenn ja, prüft diese Funktion, ob clientseitiger Validierungscode verwendet wird. Wenn dies der Fall ist, wird die von uns definierte Funktion PleaseWait() am Ende des vorhandenen Onclick-Codes hinzugefügt, unmittelbar nach der vom Client überprüften Boolin-Variablen Page_IsValid. Diese Variable gibt an, ob die Validierungskontrolle verwendet wird. Wenn der Wert von Page_IsValid falsch ist, wird die Meldung „Bitte warten“ nicht angezeigt. Wird angezeigt, wenn True.
privater String ModifyJavaScriptOnClick(string sHtml)
{
// Danke an CodeProject-Mitglied KJELLSJ (Kjell-Sverre Jerijaervi)
// für Code-Ideen, damit die Schaltfläche mit der clientseitigen Validierungszeichenfolge funktioniert
sReturn = "";
string sPleaseWaitCode = GeneratePleaseWaitJavascript();
// ist ein onclick-Attribut vorhanden?
Regex rOnclick = new Regex("onclick="(?<onclick>[^"]*)");
Match mOnclick = rOnclick.Match(sHtml);
if (mOnclick.Success)
{
// es gibt ein vorhandenes onclick-Attribut;
// füge unseren Code am Ende hinzu; wenn clientseitig
// Validierung wurde durchgeführt, stellen Sie sicher
// wir prüfen, ob die Seite gültig ist;
string sExisting = mOnclick.Groups["onclick"].Value;
Zeichenfolge sReplace = sExisting
+ (sExisting.Trim().EndsWith(";") ? "" : "; ");
if (IsValidatorIncludeScript() && this.CausesValidation)
{
// Code einschließen, um zu prüfen, ob die Seite gültig ist
string sCode = „if (Page_IsValid)“ + sPleaseWaitCode
+ " return Page_IsValid;";
// unseren Code am Ende des vorhandenen Onclick-Codes hinzufügen;
sReplace = sReplace + sCode;
}
anders
{
// Machen Sie sich keine Sorgen, dass die Seite gültig ist.
sReplace = sReplace + sPleaseWaitCode;
}
// Ersetzen Sie jetzt unseren Onclick-Code
sReplace = "onclick="" + sReplace;
sReturn = rOnclick.Replace(sHtml, sReplace);
}
anders
{
// es ist kein onclick-Attribut vorhanden;
// unsere hinzufügen
int i = sHtml.Trim().Length - 2;
string sInsert = " onclick="" + sPleaseWaitCode + "" ";
sReturn = sHtml.Insert(i, sInsert);
}
return sReturn;
}
IsValidatorIncludeScript() verwendet die obige Prüfung, um zu sehen, ob ein Standard-Javascript-Codeblock für das asp.net-Validierungssteuerelement auf der Seite registriert ist. Im Folgenden wird eine einfache Methode verwendet, um zu testen, ob Validierungscode und Variablen wie Page_IsValid vorhanden sind.
privater bool IsValidatorIncludeScript()
{
// TRUE zurückgeben, wenn diese Seite Javascript registriert hat
// für clientseitige Validierung; dieser Code darf nicht registriert werden
// wenn ASP.NET erkennt, was es denkt (richtig oder falsch)
// ist ein Down-Level-Browser.
return this.Page.IsStartupScriptRegistered("ValidatorIncludeScript");
} Das folgende GeneratePleaseWaitJavascript() erstellt die im onclick-Attribut enthaltene Javascript-Funktion PleaseWait(). Wir können das gewünschte Layout bestimmen, indem wir die Eigenschaften des Steuerelements überprüfen.
privater String GeneratePleaseWaitJavascript()
{
// einen JavaScript-Funktionsaufruf „PleaseWait()“ erstellen
// geeignet für die Verwendung in einem Onclick-Event-Handler
string sMessage = "";
string sText = _pleaseWaitText;
string sImage = (_pleaseWaitImage != String.Empty
? string.Format(
"<img src="{0}" align="absmiddle" alt="{1}"/>"
, _pleaseWaitImage, _pleaseWaitText )
: String.Empty);
// Legen Sie das Layout basierend auf PleaseWaitType fest
Schalter (_pleaseWaitType)
{
case PleaseWaitTypeEnum.TextThenImage:
sMessage = sText + sImage;
brechen;
case PleaseWaitTypeEnum.ImageThenText:
sMessage = sImage + sText;
brechen;
case PleaseWaitTypeEnum.TextOnly:
sMessage = sText;
brechen;
case PleaseWaitTypeEnum.ImageOnly:
sMessage = sImage;
brechen;
}
// den letzten Codeblock zurückgeben
string sCode = string.Format(
"PleaseWait('pleaseWaitButtonDiv_{0}',
'pleaseWaitButtonDiv2_{1}', '{2}');"
, this.ClientID, this.ClientID, sMessage);
sCode = sCode.Replace(""", """);
return sCode;
}
Wenn Sie ein PleaseWaitImage angeben, müssen Sie einen zusätzlichen Javascript-Code einfügen, um den Client zu benachrichtigen, das Bild vorab zu laden. Die Registrierung dieses Skripts sollte in der überschriebenen OnPreRender-Methode erscheinen. Der registrierte Schlüssel ist der Name des Bildes; wenn mehrere Schaltflächen dasselbe Bild verwenden, muss das Vorladeskript nur einmal implementiert werden. Mithilfe eines regulären Ausdrucks wird hier eine Javascript-Bildvariable erstellt, um sicherzustellen, dass Sonderzeichen (z. B. Schrägstriche in Dateipfaden) in Unterstriche umgewandelt werden.
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender (e);
// Wenn wir ein Bild verwenden, registrieren Sie etwas Javascript
// für das clientseitige Vorladen von Bildern
if (_pleaseWaitImage != String.Empty
&& _pleaseWaitType != PleaseWaitTypeEnum.TextOnly)
RegisterJavascriptPreloadImage(_pleaseWaitImage);
}
private void RegisterJavascriptPreloadImage(string sImage)
{
Regex rex = new Regex("[^a-zA-Z0-9]");
string sImgName = "img_" + rex.Replace(sImage, "_")
;
sb.Append("<script language='JavaScript'>");
sb.Append("if (document.images) { ");
sb.AppendFormat("{0} = new Image();", sImgName);
sb.AppendFormat("{0}.src = "{1}";", sImgName, sImage);
sb.Append(" } ");
sb.Append("</script>");
this.Page.RegisterClientScriptBlock(sImgName + "_PreloadScript",
sb.ToString());
}
Clientseitige Funktionen
Die eingebettete Textdatei javascript.txt enthält das <div>, das die Schaltfläche verbirgt, und den clientseitigen Code, der die Meldung oder das Bild „Bitte warten“ anzeigt. Diese Codes werden in die private Methode RegisterJavascriptFromResource() geladen, die in der überschriebenen OnInit()-Methode aufgerufen wird. Diese Methode ruft die generische Methode GetEmbeddedTextFile() auf, die die Datei als Quelle lädt und den Inhalt als String zurückgibt.
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
// Der clientseitige Javascript-Code bleibt erhalten
// in einer eingebetteten Ressource; das Skript laden
// und registriere es auf der Seite.
RegisterJavascriptFromResource();
}
private void RegisterJavascriptFromResource()
{
// die eingebettete Textdatei „javascript.txt“ laden
// und seinen Inhalt als clientseitiges Skript registrieren
string sScript = GetEmbeddedTextFile("javascript.txt");
this.Page.RegisterClientScriptBlock("PleaseWaitButtonScript", sScript);
}
privater String GetEmbeddedTextFile(string sTextFile)
{
// generische Funktion zum Abrufen des Inhalts
// einer eingebetteten Textdateiressource als Zeichenfolge
// Wir erhalten die ausführende Assembly und leiten sie ab
// der Namespace, der den ersten Typ in der Assembly verwendet
Assembly a = Assembly.GetExecutingAssembly();
String sNamespace = a.GetTypes()[0].Namespace;
// mit der Assembly und dem Namespace erhalten wir das
//eingebettete Ressource als Stream
Stream s = a.GetManifestResourceStream(
string.Format("{0}.{1}", sNamespace, sTextFile)
);
// den Inhalt des Streams in einen String lesen
StreamReader sr = neue StreamReader(s);
String sContents = sr.ReadToEnd();
sr.Close();
s.Close();
return sContents;
}
Die eingebettete Ressource javascript.txt enthält die clientseitige Methode PleaseWait(), die im Javascript-Onclick-Handler der Schaltfläche ausgeführt wird. Dieser Code ruft auch eine clientseitige Methode HideDiv() auf, um den Container <div> der Schaltfläche auszublenden, und fügt dann die Informationen oder das Bild in das zuvor leere <div>-Tag ein, indem das innerHTML-Attribut festgelegt wird. Die Hilfsfunktion GetDiv() gibt ein <div>-Objekt mit der ID zurück, indem sie document.getElementById, document.all und document.layers überprüft und so die Kompatibilität mit verschiedenen Browsern gewährleistet. Unten finden Sie den gesamten Code von javascript.txt:
<script language="JavaScript">
Funktion GetDiv(sDiv)
{
vardiv;
if (document.getElementById)
div = document.getElementById(sDiv);
sonst wenn (document.all)
div = eval("window." + sDiv);
sonst wenn (document.layers)
div = document.layers[sDiv];
anders
div = null;
return div;
}
Funktion HideDiv(sDiv)
{
d = GetDiv(sDiv);
wenn(d)
{
if (document.layers) d.visibility = "hide";
sonst d.style.visibility = "hidden";
}
}
Funktion PleaseWait(sDivButton, sDivMessage, sInnerHtml)
{
HideDiv(sDivButton);
var d = GetDiv(sDivMessage);
if (d) d.innerHTML = sInnerHtml;
}
</script>
Ursprünglicher Link: http://www.codeproject.com/aspnet/PleaseWaitButton.asp
Quellprojekt herunterladen – 7 KB
Demo-Projekt herunterladen – 30 KB
http://www.cnblogs.com/jeffamy/archive/2006/08/20/481952.html