บทนำ
การแสดงข้อความ "โปรดรอ" หรือภาพเคลื่อนไหว GIF มักจะมีประโยชน์ในระหว่างกระบวนการส่งแบบฟอร์มของเว็บแอปพลิเคชัน โดยเฉพาะอย่างยิ่งเมื่อกระบวนการส่งใช้เวลานาน ฉันเพิ่งพัฒนาโปรแกรมการส่งแบบสำรวจที่ผู้ใช้ภายในอัปโหลดสเปรดชีต Excel ผ่านทางหน้าเว็บ โปรแกรมจะแทรกข้อมูลสเปรดชีตที่อัปโหลดลงในฐานข้อมูล กระบวนการนี้ใช้เวลาเพียงไม่กี่วินาที แต่แม้ว่าจะเป็นเพียงไม่กี่วินาที แต่ก็เป็นกระบวนการรอที่ชัดเจนมากจากมุมมองของหน้าเว็บ ในระหว่างการทดสอบโปรแกรม ผู้ใช้บางรายคลิกปุ่มอัปโหลดซ้ำๆ ดังนั้นจึงมีประโยชน์ในการจัดเตรียมข้อความภาพเพื่อบอกผู้คนว่าการอัปโหลดอยู่ในระหว่างดำเนินการ และซ่อนปุ่มอัพโหลดพร้อมกันเพื่อป้องกันการคลิกหลายครั้ง ตัวควบคุมที่แนะนำที่นี่คือคลาสย่อยของตัวควบคุมปุ่ม ซึ่งสาธิตวิธีการห่อหุ้มโค้ด JavaScript ฝั่งไคลเอ็นต์ในตัวควบคุมเซิร์ฟเวอร์ ASP.NET เพื่อให้ฟังก์ชันที่สะดวก
แม้ว่าจะมีตัวอย่างจาวาสคริปต์มากมายที่สามารถใช้เพื่อบรรลุเป้าหมายนี้ แต่ฉันพบปัญหาบางอย่างเมื่อฉันพยายามสรุปฟังก์ชันเหล่านี้ลงในตัวควบคุม ASP.NET ก่อนอื่นฉันพยายามทำให้ปุ่มใช้งานไม่ได้ผ่านตัวจัดการ javascript onclick และแทนที่ด้วยข้อความอื่น แต่ฉันพบว่ามันยุ่งยากมาก เนื่องจากจะขัดขวางการทำงานของเหตุการณ์การคลิกบนฝั่งเซิร์ฟเวอร์ asp.net ในที่สุดสิ่งที่ได้ผลและได้รับการสนับสนุนที่ดีสำหรับเบราว์เซอร์ต่างๆ คือการแสดงปุ่มในแท็ก div div สามารถซ่อนได้และไม่ขัดขวางเหตุการณ์การคลิกของ asp.net
การใช้ตัวควบคุม
เนื่องจากเป็นอนุพันธ์ของการควบคุมปุ่มปกติ ฟังก์ชันของ PleaseWaitButton จึงเหมือนกันโดยพื้นฐาน ใช้คุณสมบัติเพิ่มเติมสามประการในการจัดการการแสดงข้อความหรือรูปภาพ "โปรดรอ" เมื่อคลิกปุ่ม
กรุณารอข้อความ
นี่คือข้อความฝั่งไคลเอ็นต์ที่แสดงขึ้น และหากมีอยู่ จะแทนที่ปุ่มเมื่อมีการคลิกปุ่ม
กรุณารอสักครู่ภาพ
นี่คือไฟล์รูปภาพ (เช่น รูปภาพ GIF แบบเคลื่อนไหว) ที่แสดงขึ้น และหากมีอยู่ ก็จะแทนที่ปุ่มเมื่อมีการคลิก คุณลักษณะนี้จะกลายเป็นแอตทริบิวต์ src ในแท็ก <img>
กรุณารอสักครู่ประเภท
ค่าการแจงนับ PleaseWaitTypeEnum ค่าใดค่าหนึ่ง: TextOnly, ImageOnly, TextThenImage หรือ ImageThenText ควบคุมการจัดวางข้อความและรูปภาพ
ด้านล่างนี้เป็นตัวอย่างไฟล์ .aspx ที่แสดงชุด PleastWaitButton พร้อมชุด PleaseWaitText และ PleaseWaitImage
<%@ ภาษาของเพจ = "C#" %>
<%@ ลงทะเบียน TagPrefix="cc1" Namespace="JavaScriptControls"
Assembly = "PleaseWaitButton" %>
<script runat = "เซิร์ฟเวอร์">
โมฆะส่วนตัว PleaseWaitButton1_Click (ผู้ส่งวัตถุ System.EventArgs e)
-
// ตัวจัดการเหตุการณ์คลิกฝั่งเซิร์ฟเวอร์;
// จำลองบางสิ่งที่อาจใช้เวลานาน
// เช่นการอัพโหลดไฟล์หรือการประมวลผลเซิร์ฟเวอร์ที่ใช้เวลานาน
DateTime dt = DateTime.Now.AddSeconds(5);
ในขณะที่ (DateTime.Now < dt)
-
// ไม่ทำอะไรเลย จำลองการหยุดชั่วคราว 5 วินาที
-
// ที่ส่วนท้ายของลูปจะแสดงข้อความแสดงความสำเร็จ
// และซ่อนแบบฟอร์มการส่ง
panelSuccess.Visible = จริง;
PleaseWaitButton1.Visible = เท็จ;
-
</สคริปต์>
<html>
<หัว>
<title>กำลังทดสอบ กรุณารอปุ่ม</title>
</หัว>
<ร่างกาย>
<form id="Form1" method="post" runat="server">
<P>การทดสอบการควบคุม PleaseWaitButton</p>
<cc1:PleaseWaitButton id="PleaseWaitButton1" runat="เซิร์ฟเวอร์"
Text="คลิกฉันเพื่อเริ่มกระบวนการที่ใช้เวลานาน"
PleaseWaitText="กรุณารอสักครู่"
PleaseWaitImage="pleaseWait.gif"
OnClick="PleaseWaitButton1_Click" />
<asp:แผง id = "panelSuccess" runat = "เซิร์ฟเวอร์"
มองเห็นได้ = "เท็จ">
ขอขอบคุณที่ส่งแบบฟอร์มนี้
ผู้ใช้ที่เจ๋งที่สุดที่ฉันเคยยินดีให้บริการ
ไม่จริง ๆ ฉันหมายถึงมีคนอื่น ๆ แน่นอน
แต่คุณอยู่ในชั้นเรียนด้วยตัวเองจริงๆ
</asp:แผง>
</แบบฟอร์ม>
</ร่างกาย>
</html>
มันทำงานอย่างไร
ตัวควบคุม PleaseWaitButton แสดงผลปุ่ม ASP.NET มาตรฐานภายในแท็ก <div> นอกจากนี้ยังแสดงแท็ก <div> ว่างสำหรับข้อมูล/รูปภาพ เมื่อคลิกปุ่ม การซ่อนปุ่มและการแสดงข้อมูลจะถูกควบคุมโดยฟังก์ชัน Javascript (ดูฟังก์ชันไคลเอ็นต์ด้านล่าง) เพื่อความสะดวก การใช้งานโค้ดไคลเอนต์จาวาสคริปต์ที่จำเป็นทั้งหมดได้รับการจัดการโดยการควบคุมเซิร์ฟเวอร์ PleaseWaitButton
เนื่องจาก PleaseWaitButton ใช้ javascript onclick handler ของตัวเอง เราจึงต้องดำเนินการขั้นตอนพิเศษบางอย่างเพื่อรักษาตัวจัดการ onclick เดิมไว้ และอนุญาตให้ส่วนควบคุมเรียกใช้โค้ดตรวจสอบความถูกต้องฝั่งไคลเอ็นต์บางส่วนได้หมดจด เพื่อให้บรรลุเป้าหมายนี้ ขั้นแรกเราจะกู้คืนคลาสฐานของ Button ไปที่บัฟเฟอร์สตริง จากนั้นจึงจัดการอย่างเชี่ยวชาญเพื่อรวมโค้ด onclick ที่เรากำหนดไว้
ป้องกันแทนที่เป็นโมฆะ Render (เอาต์พุต HtmlTextWriter)
-
// ส่งออก html ของปุ่ม (พร้อมคุณสมบัติ)
// ไปยัง HtmlTextWriter จำลอง
StringWriter sw = StringWriter ใหม่ ();
HtmlTextWriter wr = HtmlTextWriter ใหม่ (sw);
ฐาน Render(wr);
สตริง sButtonHtml = sw.ToString();
wr.ปิด();
sw.ปิด();
// ตอนนี้แก้ไขโค้ดเพื่อรวมตัวจัดการ "onclick"
// ด้วยฟังก์ชัน PleaseWait() ของเราที่ถูกเรียกอย่างเหมาะสม
// หลังจากการตรวจสอบความถูกต้องฝั่งไคลเอ็นต์
sButtonHtml = แก้ไขJavaScriptOnClick(sButtonHtml);
// ก่อนที่จะเรนเดอร์ปุ่ม ให้ส่งออกค่าว่าง <div>
// ที่จะเติมข้อมูลฝั่งไคลเอ็นต์ผ่านจาวาสคริปต์
// พร้อมข้อความ "โปรดรอสักครู่"
output.Write(string.Format("<div id='pleaseWaitButtonDiv2_{0}'>",
this.ClientID));
output.Write("</div>");
// เรนเดอร์ปุ่มในแท็ก <div> แบบห่อหุ้มของตัวเอง
output.Write(string.Format("<div id='pleaseWaitButtonDiv_{0}'>",
this.ClientID));
เอาท์พุทเขียน(sButtonHtml);
เอาท์พุทเขียน("</div>");
-
เทคนิคการลดปุ่มลงเหลือบัฟเฟอร์สตริงแล้วประมวลผลเนื้อหา onclick นี้ถือเป็นการแฮ็กอย่างแน่นอน แต่ช่วยให้เราสามารถใช้โค้ดตรวจสอบมาตรฐานในคลาสปุ่มพาเรนต์ จากนั้นจึงใช้การเรียกใช้ฟังก์ชัน Javascript PleaseWait() ของเรา หากไม่ทำเช่นนี้ เราจะต้องใช้การเรียกใช้ฟังก์ชัน PleaseWait() ในแอตทริบิวต์ onclick ก่อนโค้ดตรวจสอบ เว้นแต่ว่าเรายินดีที่จะแทนที่การเรนเดอร์แอตทริบิวต์ของคลาสปุ่มหลักโดยสมบูรณ์ ด้วยวิธีนี้แม้ว่าจะมีข้อผิดพลาดในการป้อนข้อมูลบนเพจ แต่จะมีผลในการซ่อนปุ่มและแสดงข้อความ "โปรดรอสักครู่" ที่เราไม่ต้องการ ดังนั้นเราจึงต้องบังคับฟังก์ชัน PleaseWait() ไคลเอนต์ของเราในตัวจัดการ onclick ให้ปรากฏขึ้นหลังจากการตรวจสอบหน้าไคลเอนต์
การปรับเปลี่ยนแอตทริบิวต์ onclick เกิดขึ้นในฟังก์ชัน ModifyJavaScriptOnClick() ฟังก์ชันนี้รับสตริง HTML ที่แสดงผลโดยปุ่ม และตรวจสอบเพื่อดูว่ามีแอตทริบิวต์ onclick อยู่หรือไม่ หากเป็นเช่นนั้น ฟังก์ชันนี้จะตรวจสอบว่ามีการใช้รหัสตรวจสอบฝั่งไคลเอ็นต์หรือไม่ หากเป็นกรณีนี้ ฟังก์ชัน PleaseWait() ที่เรากำหนดจะถูกเพิ่มที่ส่วนท้ายของโค้ด onclick ที่มีอยู่ ทันทีหลังจากที่ตัวแปรบูลิน Page_IsValid ตรวจสอบโดยไคลเอ็นต์ ตัวแปรนี้แสดงว่ามีการใช้การควบคุมการตรวจสอบหรือไม่ ถ้าค่าของ Page_IsValid เป็นเท็จ ข้อความ "โปรดรอสักครู่" จะไม่ปรากฏขึ้น แสดงว่าถ้าเป็น True
สตริงส่วนตัว ModifyJavaScriptOnClick (สตริง sHtml)
-
// ขอขอบคุณสมาชิก CodeProject KJELLSJ (Kjell-Sverre Jerijaervi)
// สำหรับแนวคิดโค้ดเพื่อให้ปุ่มทำงานกับ
สตริงการตรวจสอบฝั่งไคลเอ็นต์ sReturn = "";
string sPleaseWaitCode = GeneratePleaseWaitJavascript();
// มีแอตทริบิวต์ onclick อยู่หรือไม่
Regex rOnclick = Regex ใหม่("onclick="(?<onclick>[^"]*)");
จับคู่ mOnclick = rOnclick.Match(sHtml);
ถ้า (mOnclick.Success)
-
// มีแอตทริบิวต์ onclick ที่มีอยู่;
// เพิ่มโค้ดของเราที่ส่วนท้ายของโค้ด; หากฝั่งไคลเอ็นต์
// ตรวจสอบความถูกต้องแล้ว โปรดตรวจสอบให้แน่ใจ
// เราตรวจสอบว่าเพจนั้นถูกต้องหรือไม่
สตริง sExisting = mOnclick.Groups ["onclick"].Value;
สตริง sReplace = ที่มีอยู่
+ (sExisting.Trim().EndsWith(";") ? "" : "; ");
ถ้า (IsValidatorIncludeScript() && this.CausesValidation)
-
// ใส่โค้ดเพื่อตรวจสอบว่าเพจถูกต้องหรือไม่
สตริง sCode = "ถ้า (Page_IsValid)" + sPleaseWaitCode
+ " กลับ Page_IsValid;";
// เพิ่มโค้ดของเราต่อท้ายโค้ด onclick ที่มีอยู่
sReplace = sReplace + sCode;
-
อื่น
-
// ไม่ต้องกังวลว่าเพจจะถูกต้อง
sReplace = sReplace + sPleaseWaitCode;
}
// ตอนนี้แทนที่โค้ด onclick ของเรา
sReplace = "onclick="" + sReplace;
sReturn = rOnclick.แทนที่ (sHtml, sReplace);
-
อื่น
-
// ไม่มีแอตทริบิวต์ onclick ที่มีอยู่;
//เพิ่มของเรา
int i = sHtml.Trim().ความยาว - 2;
สตริง sInsert = " onclick="" + sPleaseWaitCode + "" ";
sReturn = sHtml.Insert(i, sInsert);
-
return sReturn;
}
IsValidatorIncludeScript() ใช้การตรวจสอบข้างต้นเพื่อดูว่ามีบล็อกโค้ด Javascript มาตรฐานสำหรับการควบคุมการตรวจสอบ asp.net ที่ลงทะเบียนกับเพจหรือไม่ ข้อมูลต่อไปนี้ใช้วิธีการง่ายๆ เพื่อทดสอบว่ามีรหัสตรวจสอบและตัวแปรเช่น Page_IsValid หรือไม่
บูลส่วนตัว IsValidatorIncludeScript()
-
// คืนค่า TRUE หากเพจนี้มีการลงทะเบียนจาวาสคริปต์
// สำหรับการตรวจสอบฝั่งไคลเอ็นต์ รหัสนี้อาจไม่สามารถลงทะเบียนได้
// ถ้า ASP.NET ตรวจพบสิ่งที่คิด (ถูกหรือผิด)
// เป็นเบราว์เซอร์ระดับล่าง
ส่งคืน this.Page.IsStartupScriptRegistered("ValidatorIncludeScript");
} GeneratePleaseWaitJavascript() ต่อไปนี้จะสร้างฟังก์ชัน PleaseWait() Javascript ที่มีอยู่ในแอตทริบิวต์ onclick เราสามารถกำหนดโครงร่างที่ต้องการได้โดยการตรวจสอบคุณสมบัติของตัวควบคุม
สตริงส่วนตัว GeneratePleaseWaitJavascript()
-
// สร้างการเรียกใช้ฟังก์ชัน JavaScript "PleaseWait()"
// เหมาะสำหรับใช้ในสตริงตัวจัดการเหตุการณ์ onclick
sMessage = "";
สตริง sText = _pleaseWaitText;
string sImage = (_pleaseWaitImage != String.Empty
? string.รูปแบบ(
"<img src="{0}" align="หน้าท้อง" alt="{1}"/>"
, _กรุณารอรูปภาพ, _กรุณารอข้อความ )
: String.Empty);
// สร้างเค้าโครงตาม PleaseWaitType
สวิตช์ (_pleaseWaitType)
-
กรณี PleaseWaitTypeEnum.TextThenImage:
sMessage = sText + sImage;
หยุดพัก;
กรณี PleaseWaitTypeEnum.ImageThenText:
sMessage = sImage + sText;
หยุดพัก;
กรณี PleaseWaitTypeEnum.TextOnly:
sMessage = sText;
หยุดพัก;
กรณี PleaseWaitTypeEnum.ImageOnly:
sMessage = sImage;
หยุดพัก;
}
// ส่งคืนโค้ดชิ้นสุดท้าย
สตริง sCode = string.Format(
"PleaseWait('pleaseWaitButtonDiv_{0}',
'pleaseWaitButtonDiv2_{1}', '{2}');"
, this.ClientID, this.ClientID, sMessage);
sCode = sCode.Replace(""", """);
กลับ sCode;
-
หากคุณระบุ PleaseWaitImage คุณต้องรวมโค้ด Javascript เพิ่มเติมเพื่อแจ้งให้ไคลเอ็นต์โหลดรูปภาพล่วงหน้า การลงทะเบียนสคริปต์นี้ควรปรากฏในวิธี OnPreRender ที่ถูกแทนที่ คีย์ที่ลงทะเบียนไว้คือชื่อของรูปภาพ หากหลายปุ่มใช้รูปภาพเดียวกัน จะต้องใช้งานสคริปต์โหลดล่วงหน้าเพียงครั้งเดียวเท่านั้น นิพจน์ทั่วไปถูกใช้ที่นี่เพื่อสร้างตัวแปรรูปภาพ Javascript เพื่อให้แน่ใจว่าอักขระพิเศษ (เช่นเครื่องหมายทับในเส้นทางไฟล์) จะถูกแปลงเป็นขีดล่าง
ป้องกันการแทนที่เป็นโมฆะ OnPreRender (EventArgs e)
-
base.OnPreRender (e);
// หากเราใช้รูปภาพ ให้ลงทะเบียนจาวาสคริปต์บางส่วน
// สำหรับการโหลดรูปภาพฝั่งไคลเอ็นต์ล่วงหน้า
ถ้า (_pleaseWaitImage != String.Empty
&& _pleaseWaitType != PleaseWaitTypeEnum.TextOnly)
ลงทะเบียนJavascriptPreloadImage(_pleaseWaitImage);
}
โมฆะส่วนตัว RegisterJavascriptPreloadImage (สตริง sImage)
-
Regex rex = Regex ใหม่ ("[^a-zA-Z0-9]");
string sImgName = "img_" + rex.Replace(sImage, "_");
StringBuilder sb = new StringBuilder();
sb.Append("<script language='JavaScript'>");
sb.ผนวก("ถ้า (document.images) { ");
sb.AppendFormat("{0} = new Image();", sImgName);
sb.AppendFormat("{0}.src = "{1}";", sImgName, sImage);
sb.ผนวก(" } ");
sb.Append("</script>");
this.Page.RegisterClientScriptBlock(sImgName + "_PreloadScript",
sb.ToString());
}
ฟังก์ชันฝั่งไคลเอ็นต์
ไฟล์ข้อความที่ฝัง javascript.txt มี <div> ที่ซ่อนปุ่มและโค้ดฝั่งไคลเอ็นต์ที่แสดงข้อความหรือรูปภาพ "โปรดรอสักครู่" รหัสเหล่านี้ถูกโหลดในเมธอดส่วนตัว RegisterJavascriptFromResource() ที่ถูกเรียกในเมธอด OnInit() ที่ถูกแทนที่ เมธอดนี้เรียกเมธอดทั่วไป GetEmbeddedTextFile() ซึ่งโหลดไฟล์เป็นแหล่งและส่งกลับเนื้อหาเป็นสตริง
การป้องกันการแทนที่เป็นโมฆะ OnInit (EventArgs e)
-
ฐาน OnInit(e);
// รหัสจาวาสคริปต์ฝั่งไคลเอ็นต์จะถูกเก็บไว้
// ในทรัพยากรที่ฝังตัว;
//และลงทะเบียนกับเพจ
ลงทะเบียนJavascriptFromResource();
-
โมฆะส่วนตัว RegisterJavascriptFromResource()
-
// โหลดไฟล์ข้อความที่ฝังไว้ "javascript.txt"
// และลงทะเบียนเนื้อหาเป็นสคริปต์ฝั่งไคลเอ็นต์
สตริง sScript = GetEmbeddedTextFile("javascript.txt");
this.Page.RegisterClientScriptBlock("PleaseWaitButtonScript", sScript);
-
สตริงส่วนตัว GetEmbeddedTextFile (สตริง sTextFile)
-
// ฟังก์ชันทั่วไปสำหรับการดึงเนื้อหา
// ของทรัพยากรไฟล์ข้อความที่ฝังเป็นสตริง
// เราจะได้แอสเซมบลีที่ดำเนินการและรับมา
// เนมสเปซที่ใช้ประเภทแรกในชุดประกอบ
แอสเซมบลี a = Assembly.GetExecutingAssembly();
String sNamespace = a.GetTypes()[0].Namespace;
// ด้วยแอสเซมบลีและเนมสเปซเราจะได้
//ฝังทรัพยากรเป็นสตรีม
สตรีม s = a.GetManifestResourceStream(
string.Format("{0}.{1}", sNamespace, sTextFile)
-
// อ่านเนื้อหาของสตรีมเป็นสตริง
StreamReader sr = StreamReader ใหม่
สตริง sContents = sr.ReadToEnd();
sr.Close();
s.Close();
กลับ sContents;
-
ทรัพยากรที่ฝัง javascript.txt มีเมธอดฝั่งไคลเอ็นต์ PleaseWait() ซึ่งดำเนินการในตัวจัดการ Javascript onclick ของปุ่ม รหัสนี้ยังเรียกใช้เมธอดฝั่งไคลเอ็นต์ HideDiv() เพื่อซ่อนคอนเทนเนอร์ของปุ่ม <div> จากนั้นจึงรวบรวมข้อมูลหรือรูปภาพลงในแท็ก <div> ที่ว่างเปล่าก่อนหน้านี้โดยการตั้งค่าแอตทริบิวต์ innerHTML ฟังก์ชันเสริม GetDiv() ส่งคืนอ็อบเจ็กต์ <div> พร้อม id โดยการตรวจสอบ document.getElementById, document.all และ document.layers เพื่อให้มั่นใจว่าเข้ากันได้กับเบราว์เซอร์ที่แตกต่างกัน ด้านล่างนี้คือโค้ดทั้งหมดของ javascript.txt:
<ภาษาสคริปต์ = "จาวาสคริปต์">
ฟังก์ชั่น GetDiv(sDiv)
-
วาร์ดิฟ;
ถ้า (document.getElementById)
div = document.getElementById(sDiv);
อย่างอื่นถ้า (document.all)
div = eval("หน้าต่าง" + sDiv);
อย่างอื่นถ้า (document.layers)
div = document.layers[sDiv];
อื่น
div = null;
กลับ div;
}
ฟังก์ชัน HideDiv(sDiv)
-
d = GetDiv(sDiv);
ถ้า(ง)
-
ถ้า (document.layers) d.visibility = "ซ่อน";
อื่น d.style.visibility = "ซ่อน";
-
}
ฟังก์ชัน PleaseWait(sDivButton, sDivMessage, sInnerHtml)
-
HideDiv(sDivButton);
var d = GetDiv(sDivMessage);
ถ้า (ง) d.innerHTML = sInnerHtml;
-
</script>
ลิงค์ต้นฉบับ: http://www.codeproject.com/aspnet/PleaseWaitButton.asp
ดาวน์โหลดซอร์สโปรเจ็กต์ - 7 Kb
ดาวน์โหลดโครงการสาธิต - 30 Kb
http://www.cnblogs.com/jeffamy/archive/2006/08/20/481952.html