使用Ajax ModalPopupExtender解決假死問題

我們知道,在web application中做大型數據處理的時候,通常頁面會進入到一個刷新的狀態,這個狀態將會持續到數據處理或計算結束之後,才能正常顯示網站的圖片信息,通常這樣做對於用戶體驗來說是不友好的,有很多方式來解決這一問題,例如使用異步數據處理或者在後臺建立一個後臺線程進行處理,這樣用戶將會在不失去與application的交互,這裏我們介紹的是使用Ajax control tookit來解決這一問題,不同於你使用異步的Callback和background 線程,這個方式非常簡單且有效,對於開發者來說,你不需要額外的工作去建立異步方法和線程。

這裏用到的Ajax控件包括ModalPopupExtender和ToolkitScriptManager。 ToolkitScriptManager和ScriptManager的作用很類似,它用於處理頁面上的組件和頁面局部刷新,生成相關的頁面客戶端代理腳本,但是相比較於ScriptManager,它可以提升下載效率和減少request的次數,所以這裏推薦使用ToolkitScriptManager控件取代ScriptManager。

ToolkitScriptManager vs ScriptManager http://www.cnblogs.com/liminzhang/archive/2007/07/31/837329.html

ModalPopupManager控件可以在用戶點擊按鈕的時候顯示一個相應的control,這個control通過設置它的TargetControlID啓用,我們可以利用它顯示一個Panel控件,而在Panel中存在我們需要顯示的Spinner image。Spinner image 由JavaScript代碼做出。

爲了方便在項目中複用這段代碼,我們將ModalPopupManger控件建立在User control中:

[本示例完整源碼下載(0分)]  http://download.csdn.net/source/3535567

現在介紹我們需要的實現方法:

首先建立一個Web Application程序,開始之前,請下載需要AjaxControlToolkit DLL文件到項目中並引用(下載地址 http://ajaxcontroltoolkit.codeplex.com/),在根目錄創建一個web頁面和一個User Control控件,因爲項目需要顯示圖片功能,需要引入一個Image文件夾,文件夾中包含一些必要的圖片文件,爲了顯示結果,我們使用一個XML文件作爲數據源,在數據處理完之後顯示XML文件上面的數據。

XML文件格式(XMLData.xml),僅僅爲了顯示結果:

<Root>
  <Person>
  <Name>Angle</Name>
  <Age>23</Age>
  <Country>United State</Country>
  <Comment>None</Comment>
  </Person>

  <Person>
  <Name>Bill</Name>
  <Age>41</Age>
  <Country>United State</Country>
  <Comment>None</Comment>
  </Person>
</Root>

UserControl中包含一個Panel控件(用於承載image和取消按鈕,在頁面進行大數據處理時候出現),一個LinkButton(用於觸發點擊事件),一個ModalPopupExtender控件(用於顯示Panel),並且包含一些JavaScript代碼,這些代碼用於加載image文件,並且每隔1秒鐘進行圖片之間的切換操作:

PopupProgress.ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PopupProgress.ascx.cs" Inherits="CSASPNETShowSpinnerImage.PopupProgress" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %> 
<script language="javascript" type="text/javascript">
    <% =LoadImage() %>
    
    // The JavaScript function can shows loaded image in Image control.
    var imgStep = 0;
    function slide()
    {
        var img = document.getElementById("PopupProgressUserControl_imgProgress");      
        if (document.all)
        {
            img.filters.blendTrans.apply();
        } 
           
        img.title=imgMessage[imgStep];  
        img.src=imgUrl[imgStep]; 
                      
        if (document.all)
        {
            img.filters.blendTrans.play();
        }
        
        imgStep = (imgStep < (imgUrl.length-1)) ? (imgStep + 1) : 0;
        (new Image()).src = imgUrl[imgStep];
    }
    setInterval("slide()",1000);

</script>
<asp:Panel ID="pnlProgress" runat="server" CssClass="modalpopup"> 
    <div class="popupcontainerLoading"> 
        <div class="popupbody"> 
            <table width="100%"> 
                <tr> 
                    <td align="center"> 
                        <asp:Image ID="imgProgress" runat="server" style="filter: blendTrans(duration=0.618)"  ImageUrl="~/Image/0.jpg"/>                       
                    </td> 
                </tr> 
                <tr> 
                    <td>
                    <asp:Button ID="btnCancel" runat="server" Text="Cancel" /></td>
                </tr>
            </table> 
        </div> 
    </div> 
</asp:Panel> 
<asp:LinkButton ID="btnLink" runat="server" Text=""></asp:LinkButton> 
<asp:ModalPopupExtender ID="mpeProgress" runat="server" TargetControlID="btnLink"
    X="500" Y="0" PopupControlID="pnlProgress" BackgroundCssClass="modalBackground" DropShadow="true"  CancelControlID="btnCancel" > 
</asp:ModalPopupExtender>


在這個PopupProgress用戶控件的後臺代碼頁面中,我們可以有一個LoadImage方法,用於加載頁面到一個Array中,並通過把這些JavaScript代碼註冊到前臺頁面中,通過<% =LoadImage()%>的方式, 你同樣可以直接寫在前臺頁面中去加載Image文件。

PopupProgress.ascx.cs

namespace CSASPNETShowSpinnerImage
{
    public partial class PopupProgress : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// This method is use to load images of customize files and 
        /// register JavaScript code on User Control page.
        /// </summary>
        /// <returns></returns>
        public string LoadImage()
        {
            StringBuilder strbScript = new StringBuilder();
            string imageUrl = "";

            strbScript.Append("var imgMessage = new Array();");
            strbScript.Append("var imgUrl = new Array();");
            string[] strs = new string[7];
            strs[0] = "Image/0.jpg";
            strs[1] = "Image/1.jpg";
            strs[2] = "Image/2.jpg";
            strs[3] = "Image/3.jpg";
            strs[4] = "Image/4.jpg";
            strs[5] = "Image/5.jpg";
            strs[6] = "Image/6.jpg";
            for (int i = 0; i < strs.Length; i++)
            {
                imageUrl = strs[i];

                strbScript.Append(String.Format("imgUrl[{0}] = '{1}';", i, imageUrl));
                strbScript.Append(String.Format("imgMessage[{0}] = '{1}';", i, imageUrl.Substring(imageUrl.LastIndexOf('.') - 1)));
            }
            strbScript.Append("for (var i=0; i<imgUrl.length; i++)");
            strbScript.Append("{ (new Image()).src = imgUrl[i]; }");
            return strbScript.ToString();
        }

    }
}


我們的這個UserControl, 算是完成了,接着我們需要在特定的地方調用它,例如建立一個Web form頁面,命名爲Default.aspx.

這個頁面需要包含ToolkitScriptManager和UpdatePanel,UpdateProgress控件,通過在局部刷新的情況調用這個UserControl:

Default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="CSASPNETShowSpinnerImage.Default" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %> 
<%@ Register src="UserControl/PopupProgress.ascx" tagname="PopupProgress" tagprefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
     <title></title>
       <style type="text/css"> 
        .modalBackground 
        { 
            background-color: Gray; 
            filter:alpha(opacity=70);
            opacity: 0.5; 
        } 
    </style> 
 </head>
 <body id="body1" runat="server" >
     <form id="form1" runat="server">
     <div>           
        <asp:ToolkitScriptManager ID="ToolkitScriptManagerPopup" runat="server" />      
        <asp:UpdatePanel ID="updatePanel" UpdateMode="Conditional" runat="server"> 
            <ContentTemplate>  
                <%=DateTime.Now.ToString() %> 
                <br /> 
                 <asp:Button ID="btnRefresh" runat="server" Text="Refresh Panel" OnClick="btnRefresh_Click" OnClientClick="document.getElementById('PopupProgressUserControl_btnLink').click();" /> 
                <br /> 
               <asp:GridView ID="gvwXMLData" runat="server">
            </asp:GridView>
            </ContentTemplate>           
        </asp:UpdatePanel> 
       
        
        
        <asp:UpdateProgress ID="updateProgress" runat="server" AssociatedUpdatePanelID="updatePanel"> 
            <ProgressTemplate> 
                <uc1:PopupProgress ID="PopupProgressUserControl" runat="server" />
            </ProgressTemplate>
        </asp:UpdateProgress>           
     </div>   
     </form>
 </body>
</html>


那麼在後臺頁面我們需要使用UpdatePanel中的這個button來模擬我們的大數據計算,這裏我們爲了模擬他,使用Threading.sleep()方法,停止主線程,並且在停止後將Xml數據綁定到GridView中,表示處理成功:

Default.aspx.cs

namespace CSASPNETShowSpinnerImage
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btnRefresh_Click(object sender, EventArgs e)
        {
            // Here we use Thread.Sleep() to suspends the thread for 10 seconds for imitating
            // an expensive, time-consuming operate of retrieve data. (Such as connect network
            // database to retrieve mass data.)
            // So in practice application, you can remove this line. 
            System.Threading.Thread.Sleep(10000);

            // Retrieve data from XML file as sample data.
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(AppDomain.CurrentDomain.BaseDirectory + "XMLFile/XMLData.xml");
            DataTable tabXML = new DataTable();
            DataColumn columnName = new DataColumn("Name", Type.GetType("System.String"));
            DataColumn columnAge = new DataColumn("Age", Type.GetType("System.Int32"));
            DataColumn columnCountry = new DataColumn("Country", Type.GetType("System.String"));
            DataColumn columnComment = new DataColumn("Comment", Type.GetType("System.String"));
            tabXML.Columns.Add(columnName);
            tabXML.Columns.Add(columnAge);
            tabXML.Columns.Add(columnCountry);
            tabXML.Columns.Add(columnComment);
            XmlNodeList nodeList = xmlDocument.SelectNodes("Root/Person");
            foreach (XmlNode node in nodeList)
            {
                DataRow row = tabXML.NewRow();
                row["Name"] = node.SelectSingleNode("Name").InnerText;
                row["Age"] = node.SelectSingleNode("Age").InnerText;
                row["Country"] = node.SelectSingleNode("Country").InnerText;
                row["Comment"] = node.SelectSingleNode("Comment").InnerText;
                tabXML.Rows.Add(row);
            }
            gvwXMLData.DataSource = tabXML;
            gvwXMLData.DataBind();
        }


    }


這樣我們的項目就算製作成功了,運行你的程序並點擊按鈕,就可以看到Spinner image的效果了,在10秒之後,你可以看到成功顯示的GridView。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章