PleaseWaitButton ASP.NET 服务器控件 2.0

分享于 

17分钟阅读

Web开发

  繁體 雙語

介绍

PleaseWaitButton控件的原始版本是 Mike Ellison为 ASP.NET 1.1 ( 感谢迈克) 编写的: http://www.codeproject.com/KB/webforms/PleaseWaitButton.aspx

我刚刚在 2.0版本中处理了 JavaScript。

在web应用程序中显示"请稍候"消息,或者是动画GIF映像,尤它的是提交过程持续几秒钟时。 防止用户单击按钮的最好方法是确保按钮的状态在初始单击时更改。

使用控件

作为它的后代,PleaseWaitButton 函数就像常规 Button 控件一样。 它公开了三个附加属性来控制在单击按钮后"请稍候"消息或者图像的显示。

  • PleaseWaitText: 这是在点击按钮时要显示的客户端文本消息( 如果有的话)。
  • PleaseWaitImage: 这是在单击按钮时显示的图像文件( 通常是动画 GIF ) ( 如果有的话)。 这里属性用作生成的<img> 标记的src 属性。
  • PleaseWaitType: PleaseWaitTypeEnum 值之一- TextOnlyImageOnlyTextThenImage 或者 ImageThenText - 它控制消息的布局和/或者图像的布局。

下面是演示a 和 PleaseWaitImage 集的 。aspx文件的示例:

<%@Pagelanguage="C#"%><%@RegisterTagPrefix="cc1"Namespace="JavaScriptControls"Assembly="PleaseWaitButton"%><scriptrunat="server">privatevoid PleaseWaitButton1_Click(object sender, System.EventArgs e)
 {
 // Server-side Click event handler; // simulate something that could take a long time,// like a file upload or time-consuming server processing DateTime dt = DateTime.Now.AddSeconds(5);
 while (DateTime.Now < dt)
 {
 // do nothing; simulate a 5-second pause }
 // at the end of the loop display a success message// and hide the submit form  panelSuccess.Visible = true;
 PleaseWaitButton1.Visible = false;
 }</script><html><head><title>Testing PleaseWaitButton</title></head><body><formid="Form1"method="post"runat="server"><P>Testing the PleaseWaitButton control.</p><cc1:PleaseWaitButtonid="PleaseWaitButton1"runat="server"Text="Click me to start a time-consuming process"PleaseWaitText="Please Wait..."PleaseWaitImage="pleaseWait.gif"OnClick="PleaseWaitButton1_Click"/><asp:Panelid="panelSuccess"runat="server"visible="false"> Thank you for submitting this form. You are truly 
 the coolest user I've ever had the pleasure of serving.
 No, really, I mean it. There have been others, sure,
 but you are really in a class by yourself. 
 </asp:Panel></form></body></html>

使用指导

PleaseWaitButton 控件在 <div> 标记中呈现标准的ASP.NET Button。 它还为消息/图像呈现一个最初空的<div>。 JavaScript函数( 显示 below 在 客户端函数 ) 控制隐藏按钮并在单击"请稍候"消息时显示消息。 为了方便,PleaseWaitButton 服务器控件处理所有必要的JavaScript客户端代码的呈现。

因为 PleaseWaitButton 呈现自己的JavaScript onclick 处理程序,所以需要额外的措施来保留现有的onclick 处理程序,并允许控件与客户端验证代码干净地。 为了实现这个目的,基本 Button 首先呈现给字符串缓冲区,然后操作它以包含我们的定制 onclick 代码。

protectedoverridevoid Render(HtmlTextWriter output)
{
 // Output the button's html (with attributes)// to a dummy HtmlTextWriter StringWriter sw = new StringWriter();
 HtmlTextWriter wr = new HtmlTextWriter(sw);
 base.Render(wr);
 string sButtonHtml = sw.ToString();
 wr.Close();
 sw.Close();
 // now modify the code to include an"onclick" handler// with our PleaseWait() function called appropriately// after any client-side validation. sButtonHtml = ModifyJavaScriptOnClick(sButtonHtml);
 // before rendering the button, output an empty <div>// that will be populated client-side via javascript// with a"please wait" message" output.Write(string.Format("<div id='pleaseWaitButtonDiv2_{0}'>",
 this.ClientID));
 output.Write("</div>");
 // render the button in an encapsulating <div> tag of its own output.Write(string.Format("<div id='pleaseWaitButtonDiv_{0}'>",
 this.ClientID));
 output.Write(sButtonHtml);
 output.Write("</div>");
}

将按钮呈现到字符串缓冲区,然后操作它的onclick 内容的技术当然是 hack。 不过,它允许我们呈现 PleaseWait() JavaScript调用 Button 类提供的标准验证代码。 我们必须先将 PleaseWait() 函数调用中的验证代码呈现出来,否则才能完全重写父类 Button的属性呈现。 即使页面上有数据输入错误,也会产生隐藏按钮和显示"请稍候"消息的不良效果。 客户端 PleaseWait() 函数的调用必须强制在 onclick 处理程序的客户端页验证后发生。

onclick 属性的修改发生在 ModifyJavaScriptOnClick() 函数中。 这将获取按钮的呈现HTML字符串并检查它是否存在现有的onclick 属性。 如果是,函数也会检查客户端端验证代码是否使用。 在这种情况下,我们的自定义 PleaseWait() 函数调用被添加到现有 onclick 代码的末尾,后面的检查是of变量 Page_IsValid。 验证控件使用时,将出现这里变量。 如果 Page_IsValid 在客户端是 false,则"请稍候"消息将停止。 如果 Page_IsValid 是客户端上的true,则会显示"请稍候"消息。

privatestring ModifyJavaScriptOnClick(string sHtml)
{
 // Thanks to CodeProject member KJELLSJ (Kjell-Sverre Jerijaervi)// for code ideas to allow the button to work with client-side validationstring sReturn = "";
 string sPleaseWaitCode = GeneratePleaseWaitJavascript();
 // is there an existing onclick attribute? Regex rOnclick = new Regex("onclick="(?<onclick>[^"]*)");
 Match mOnclick = rOnclick.Match(sHtml);
 if (mOnclick.Success)
 {
 // there is an existing onclick attribute;// add our code to the end of it; if client-side// validation has been rendered, make sure// we check to see if the page is valid;string sExisting = mOnclick.Groups["onclick"].Value;
 string sReplace = sExisting 
 + (sExisting.Trim().EndsWith(";")? "" : ";");
 if (IsValidatorIncludeScript() && this.CausesValidation)
 {
 // include code to check if the page is validstring sCode = "if (Page_IsValid)" + sPleaseWaitCode 
 + " return Page_IsValid;";
 // add our code to the end of the existing onclick code; sReplace = sReplace + sCode;
 }
 else {
 // don't worry about the page being valid; sReplace = sReplace + sPleaseWaitCode;
 }
 // now substitute our onclick code sReplace = "onclick="" + sReplace;
 sReturn = rOnclick.Replace(sHtml, sReplace);
 }
 else {
 // there isn't an existing onclick attribute;// add oursint i = sHtml.Trim().Length - 2;
 string sInsert = " onclick="" + sPleaseWaitCode + """;
 sReturn = sHtml.Insert(i, sInsert); 
 }
 return sReturn;
}

函数 IsValidatorIncludeScript() 引用 上面 检查 ASP.NET 验证控件使用的标准 JavaScript block 是否已经注册到页面。 这是测试验证代码和 Page_IsValid 等变量是否可用的一种方便的方法。

privatebool IsValidatorIncludeScript()
{
 // return TRUE if this page has registered javascript// for client-side validation; this code may not be registered// if ASP.NET detects what it thinks (correctly or incorrectly)// is a down-level browser.//Changed from origianl code to. NET 2.0 formatreturnthis.Page.ClientScript.IsStartupScriptRegistered("ValidatorIncludeScript");
}

函数 GeneratePleaseWaitJavascript() 构造了包含在 onclick 属性中的PleaseWait() JavaScript函数调用。 控制属性以确定所需的布局。

privatestring GeneratePleaseWaitJavascript()
{
 // create a JavaScript"PleaseWait()" function call// suitable for use in an onclick event handlerstring sMessage = "";
 string sText = _pleaseWaitText;
 string sImage = (_pleaseWaitImage!= String.Empty 
? string.Format(
 "<img src="{0}" align="absmiddle" alt="{1}"/>", _pleaseWaitImage, _pleaseWaitText )
 : String.Empty);
 // establish the layout based on PleaseWaitTypeswitch (_pleaseWaitType)
 {
 case PleaseWaitTypeEnum.TextThenImage:
 sMessage = sText + sImage;
 break;
 case PleaseWaitTypeEnum.ImageThenText:
 sMessage = sImage + sText;
 break;
 case PleaseWaitTypeEnum.TextOnly:
 sMessage = sText;
 break;
 case PleaseWaitTypeEnum.ImageOnly:
 sMessage = sImage;
 break;
 }
 // return the final code chunkstring sCode = string.Format(
 "PleaseWait('pleaseWaitButtonDiv_{0}', 
 'pleaseWaitButtonDiv2_{1}', '{2}');", this.ClientID, this.ClientID, sMessage);
 sCode = sCode.Replace(""", "&quot;");
 return sCode;
}

如果指定了 PleaseWaitImage,则包含一个附加的JavaScript block,指示客户机预先加载映像。 这里脚本的注册发生在重写的OnPreRender 方法中。 注册密钥基于图像 NAME ;如果多个按钮在同一图像上使用,则预加载脚本只显示一次。 正则表达式用于创建JavaScript图像变量,确保非字母化字符( 文件路径中的斜线) 被转换为下划线。

protectedoverridevoid OnPreRender(EventArgs e)
{
 base.OnPreRender (e);
 // If we're using an image, register some javascript// for client-side image preloadingif (_pleaseWaitImage!= String.Empty 
 && _pleaseWaitType!= PleaseWaitTypeEnum.TextOnly)
 RegisterJavascriptPreloadImage(_pleaseWaitImage);
}privatevoid RegisterJavascriptPreloadImage(string sImage)
{
 Regex rex = new Regex("[^a-zA-Z0-9]");
 string sImgName = "img_" + rex.Replace(sImage, "_"); 
 StringBuilder sb = new StringBuilder();
 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>");
 //Changed from origianl code to. NET 2.0 format this.Page.ClientScript.RegisterStartupScript(this.GetType(), sImgName + 
 "_PreloadScript",sb.ToString());
}

客户端功能

嵌入的文本文件 javascript.txt 包含用于隐藏按钮的<div> 和显示"请稍候"消息/图像的客户端代码。 这里代码在重写的OnInit() 方法中加载,并调用 private 方法 RegisterJavascriptFromResource()。 这里方法调用更通用的方法 GetEmbeddedTextFile(),它加载嵌入作为资源的文本文件,并将内容作为字符串返回。

protectedoverridevoid OnInit(EventArgs e)
{
 base.OnInit(e);
 // the client-side javascript code is kept// in an embedded resource; load the script// and register it with the page. RegisterJavascriptFromResource();
}privatevoid RegisterJavascriptFromResource()
{ 
 // load the embedded text file"javascript.txt"// and register its contents as client-side scriptstring sScript = GetEmbeddedTextFile("javascript.txt"); 
 //Changed from origianl code to. NET 2.0 format this.Page.ClientScript.RegisterStartupScript(this.GetType(), 
 "PleaseWaitButtonScript", sScript);
}privatestring GetEmbeddedTextFile(string sTextFile)
{
 // generic function for retrieving the contents// of an embedded text file resource as a string// we'll get the executing assembly, and derive// the namespace using the first type in the assembly Assembly a = Assembly.GetExecutingAssembly();
 String sNamespace = a.GetTypes()[0].Namespace;
 // with the assembly and namespace, we'll get the// embedded resource as a stream Stream s = a.GetManifestResourceStream(
 string.Format("{0}.{1}", sNamespace, sTextFile)
 );
 // read the contents of the stream into a string StreamReader sr = new StreamReader(s);
 String sContents = sr.ReadToEnd();
 sr.Close();
 s.Close();
 return sContents;
}

xml - javascript.txt 内置资源包含客户端方法 PleaseWait(),它在按钮的JavaScript onclick 处理程序中执行。 这里代码调用客户端方法 HideDiv() 以隐藏按钮 <div>,然后通过设置它的innerHTML 属性填充以前空的<div> 标记。 helper 函数 GetDiv() 尝试维护 跨浏览器 兼容性,检查 document.getElementByIddocument.alldocument.layers,以返回给定它的ID的<div> 对象。 javascript.txt 中的完整客户端代码如下:

<script language="JavaScript">function GetDiv(sDiv)
{
 var div;
 if (document.getElementById)
 div = document.getElementById(sDiv);
 elseif (document.all)
 div = eval("window." + sDiv);
 elseif (document.layers)
 div = document.layers[sDiv];
 else div = null;
 return div;
}function HideDiv(sDiv)
{
 d = GetDiv(sDiv);
 if (d)
 {
 if (document.layers) d.visibility = "hide";
 else d.style.visibility = "hidden";
 }
}function PleaseWait(sDivButton, sDivMessage, sInnerHtml)
{
 if (!ValidatorOnSubmit()) return; //Added to original code HideDiv(sDivButton);
 var d = GetDiv(sDivMessage);
 if (d) d.innerHTML = sInnerHtml;
}
</script>

摘要

这里提供的ASP.NET 服务器控制 PleaseWaitButton<div> 标签中呈现一个标准 Button,用户端JavaScript表示一个"请稍候"消息或者图像。 这样的消息可以为用户提供有用的视觉提示来处理时间,并防止意外多次点击。 尽管控件要使用客户端验证器充分工作,但这种复杂性可以封装在服务器控件中。

确认

我刚刚复制并粘贴了 98%个以上的文章,并对它的进行了修改。


相关文章