国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

ASP.NET服務器控件PleaseWaitButton[翻譯]

2019-11-18 17:03:09
字體:
供稿:網(wǎng)友

Introduction

  在web application的表單提交過程中顯示“please wait”信息或者是gif動畫圖片通常是很有用的,特別是提交過程比較久的情況。我最近開發(fā)了一個調(diào)查提交程序,在程序里內(nèi)部用戶通過一個網(wǎng)頁上傳Excel電子表格。程序?qū)⑸蟼鞯碾娮颖砀駭?shù)據(jù)插入到數(shù)據(jù)庫中。這個過程只需要幾秒鐘,但即便是幾秒鐘,在網(wǎng)頁是看來卻是非常明顯的等待過程。在程序測試的時候,一些用戶重復地點擊上傳按鈕。因此,提供一個視覺的信息來告訴人們上傳正在進行中是很有用的。并同時把上傳按鈕一起隱藏掉,以防止多次點擊。這里介紹的控件是Button控件的子類,它演示了如何把客戶端javascript代碼封裝在asp.net服務器控件中來提供便利的功能。

  雖然外面已經(jīng)有很多Javascript的例子來完成這件事情,但當我試圖把這些功能封裝到asp.net控件中時我發(fā)現(xiàn)了一些問題。我最開始嘗試通過javascript的onclick句柄來使button無效,并用另外的文本取代。但我發(fā)現(xiàn)很棘手,這樣會妨礙到asp.net服務器端的click事件的功能。而最終行得通的,并且對不同瀏覽器也有很好支持的方法是,讓button在div標記中呈現(xiàn)。div可以隱藏并且不妨礙asp.net的click事件。

Using the control

  作為正常的button控件的派生,PleaseWaitButton的功能與它基本一樣。它通過三個附加的屬性來管理當按鈕被點擊后"please Wait"信息或圖片的顯示。

PleaseWaitText
  這是顯示的客戶端文本信息,如果存在,當按鈕被點擊它將取代按鈕。
PleaseWaitImage
  這是顯示的圖像文件(比如gif動畫圖像),如果存在,當按鈕被點擊它將取代按鈕。這個屬性將變成<img>標記中的src屬性。
PleaseWaitType
  PleaseWaitTypeEnum枚舉值之一:TextOnly,ImageOnly,TextThenImage,或者ImageThenText。它控制消息和圖片的布局。

  下面是一個.aspx文件示例,它演示了一個設置了PleaseWaitText和PleaseWaitImage的PleastWaitButton。

 

<%@ Page language="C#" %>
<%@ Register Tag                             Assembly="PleaseWaitButton" %>

<script runat="server">
    private void 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>
        <form id="Form1" method="post" runat="server">
 
            <P>Testing the PleaseWaitButton control.</p>
 
            <cc1:PleaseWaitButton id="PleaseWaitButton1" runat="server"
                     Text="Click me to start a time-consuming process"
                     PleaseWaitText="Please Wait "
                     PleaseWaitImage="pleaseWait.gif"
                     OnClick="PleaseWaitButton1_Click" />
 
            <asp:Panel id="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>


How It Works

  PleaseWaitButton控件在<div>標記中呈現(xiàn)了一個標準的asp.net Button。它也呈現(xiàn)了一個空的<div>標記給
信息/圖像。在點擊按鈕時,由Javascript函數(shù)(見下面的客戶端函數(shù))控制按鈕的隱藏和信息的顯示。為了方便起見,由PleaseWaitButton服務器控件處理所有必需的javascript客戶端代碼的實施。
  由于PleaseWaitButton實施它自己的javascript onclick句柄,所以我們必須采取一些額外的措施來保持原有的onclick句柄,并且允許控件清晰地運行一些客戶端驗證代碼。為了達到此目的,我們首先把Button基類還原為一個字符串緩沖,然后巧妙地處理它,把我們定義的onclick代碼包含進去。


protected override void 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>");
}
  這種把button還原成一個字符串緩沖然后處理它的onclick內(nèi)容的技術是一件很危險的事情(is certainly a hack). 但它可以讓我們在父button類中實施標準的驗證代碼,然后再實現(xiàn)我們的PleaseWait() Javascript函數(shù)調(diào)用。如果不這樣做,我們只能在驗證代碼之前就在onclick屬性中實施我們的PleaseWait()函數(shù)調(diào)用,除非我們愿意完全重寫父Button類的屬性的呈現(xiàn)。這樣就算頁面上有輸入錯誤也會產(chǎn)生我們并不希望的按鈕隱藏和顯示"please wait"信息的效果。因此,我們必須在onclick句柄中強行令我們的客戶端PleaseWait()函數(shù)出現(xiàn)在客戶端頁面驗證之后。
  onclick屬性的修改發(fā)生在ModifyJavaScriptOnClick()函數(shù)中。這個函數(shù)獲取按鈕呈現(xiàn)的HTML字符串,并檢查看是否存在onclick屬性。如果是,這個函數(shù)會檢查是否有使用客戶端驗證代碼。如果是這種情況的話,我們定義的PleaseWait()函數(shù)會加在已經(jīng)存在的onclick代碼的最后面,緊跟在客戶端檢查的boolin變量Page_IsValid后面。這個變量代表是否使用了驗證控件。如果Page_IsValid的值是false,"Please wait"信息將不顯示。如果為True則顯示。
private string ModifyJavaScriptOnClick(string sHtml)
{
    // Thanks to CodeProject member KJELLSJ (Kjell-Sverre Jerijaervi)
    // for code ideas to allow the button to work with client-side validation

    string 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 valid
            string 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 ours
        int i = sHtml.Trim().Length - 2;
        string sInsert = " onclick=/"" + sPleaseWaitCode + "/" ";
        sReturn = sHtml.Insert(i, sInsert);            
    }
   
    return sReturn;

}

  這個IsValidatorIncludeScript() 利用上面的檢查來查看是否有使用頁面注冊的asp.net驗證控件的標準Javascript代碼塊。下面則用一個簡單的方法測試了是否有驗證代碼和像Page_IsValid的變量存在。
private bool 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.

    return this.Page.IsStartupScriptRegistered("ValidatorIncludeScript");
}  下面這個GeneratePleaseWaitJavascript()構建了包含在onclick屬性中的PleaseWait() Javascript函數(shù)。我們可以通過檢查控件的屬性來決定想要的布局。
private string GeneratePleaseWaitJavascript()
{
    // create a JavaScript "PleaseWait()" function call
    // suitable for use in an 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);

    // establish the layout based on PleaseWaitType
    switch (_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 chunk
    string sCode = string.Format(
        "PleaseWait('pleaseWaitButtonDiv_{0}',
                    'pleaseWaitButtonDiv2_{1}', '{2}');"
        , this.ClientID, this.ClientID, sMessage);
    sCode = sCode.Replace("/"", "&quot;");

    return sCode;
}
  如果指定了一個PleaseWaitImage,就必須包含額外的一段Javascript代碼來通知客戶端預載該圖像。這段腳本的注冊應該出現(xiàn)在重寫的OnPreRender方法中。注冊的鍵是圖像的名稱;如果多個按鈕都使用同一圖像,預載腳本只需要實施一次。這里使用了一個正則表達式來創(chuàng)建Javascript圖像變量,以保證特殊字字符(比如文件路徑中的斜線)轉(zhuǎn)化成下劃線。

 

protected override void OnPreRender(EventArgs e)
{
    base.OnPreRender (e);

    // If we're using an image, register some javascript
    // for client-side image preloading
    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, "_");

    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>");

    this.Page.RegisterClientScriptBlock(sImgName + "_PreloadScript",
                                        sb.ToString());
}

Client-side functions

  嵌入的文本文件javascript.txt包含了隱藏按鈕的<div>和顯示"please wait"信息或圖像的客戶端代碼。這些代碼在重寫的OnInit()方法中調(diào)用的私有方法RegisterJavascriptFromResource()加載。這個方法調(diào)用泛型方法GetEmbeddedTextFile() ,在這個泛型方法中把文件做為源加載而把內(nèi)容返回成字符串。


protected override void 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();
}


private void RegisterJavascriptFromResource()
{  
    // load the embedded text file "javascript.txt"
    // and register its contents as client-side script
    string sScript = GetEmbeddedTextFile("javascript.txt");
    this.Page.RegisterClientScriptBlock("PleaseWaitButtonScript", sScript);
}


private string 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;
}
  javascript.txt嵌入資源包含了按鈕在Javascript的onclick句柄中執(zhí)行的客戶端方法PleaseWait()。這段代碼也調(diào)用了一個客戶端方法HideDiv()以隱藏按鈕的容器<div>,然后通過設置innerHTML屬性把信息或圖像組裝進之前空的<div>標記中。輔助函數(shù)GetDiv()則是通過檢查document.getElementById, document.all, 和 document.layers用id返回一個<div>對象,保證了不同瀏覽器的兼容性。下面是javascript.txt的全部代碼:
<script language="JavaScript">
function GetDiv(sDiv)
{
    var div;
    if (document.getElementById)
        div = document.getElementById(sDiv);
    else if (document.all)
        div = eval("window." + sDiv);
    else if (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)
{
    HideDiv(sDivButton);
    var d = GetDiv(sDivMessage);
    if (d) d.innerHTML = sInnerHtml;
}
</script>

原文鏈接:http://www.codeproject.com/aspnet/PleaseWaitButton.asp
Download Source Project - 7 Kb
Download Demo Project - 30 Kb

http://m.survivalescaperooms.com/jeffamy/archive/2006/08/20/481952.html


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 内乡县| 临江市| 桐城市| 南靖县| 正定县| 长宁县| 洛南县| 肥城市| 镇宁| 金湖县| 溧水县| 漳州市| 温州市| 枣阳市| 石柱| 铁岭市| 离岛区| 平远县| 图们市| 康乐县| 宜春市| 陇南市| 茶陵县| 定结县| 禹城市| 岑溪市| 罗城| 西乌珠穆沁旗| 文水县| 宜兴市| 哈尔滨市| 富阳市| 丹东市| 五峰| 柞水县| 高淳县| 吉林市| 三穗县| 阿图什市| 新建县| 都昌县|