5.5 與PageMethods合作!另一種進度條實現
前面曾以UpdateProgress搭配ASP.NET Callback技巧,實現Async-Postback的進度回報功能,在了解PageMethods功能的用法之后,讀者們一定會思考,PageMethods與Callback技術同樣不會受到單一頁面同時只能有一個Async-Postback的限制,若用PageMethods來取代Callback技術,是否能更簡單地做出進度條呢?這個答案是肯定的也是否定的,肯定的原因是PageMethods可以替代Callback技術來實現此功能,否定的原因是這樣不見得會寫較少的程序代碼。不管如何,多學一種應用總是好的,程序5-12是以PageMethods取代Callback來實現進度條的.aspx源碼,程序5-13是.aspx.cs的源碼。
程序5-12
Samples\5\AdvAjaxDemo\UpdateProgressReport_WithPageMethod.aspx <%@ Page Language="C#" AutoEventWireup="true" CodeFile="UpdateProgressReport_WithPageMethod.aspx.cs" Inherits="UpdateProgressReport_WithPageMethod" %> <!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 runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="True"> </asp:ScriptManager> <script language=javascript> var prm = Sys.WebForms.PageRequestManager.getInstance(); prm.add_endRequest(EndRequest); function EndRequest(sender,args) { if($get('Button1').disabled == "disabled") { $get('Button1').disabled = ""; } } function OnSucceeded(result, userContext, methodName) { if (methodName == "GetCurrentProgress") { if(result != -1) adjustProgress(result); window.setTimeout("getProgress();",1000); } else if(methodName == "CancelCurrentProgress") { $get('Button1').disabled = ""; } } function OnFailed(error, userContext, methodName) { if(error !== null) { alert(error.get_message()); } } function cancelProcess() { PageMethods.CancelCurrentProgress($get('Hidden1'). value,OnSucceeded,OnFailed); $get('UpdateProgress1').style.display = "none"; if (prm.get_isInAsyncPostback()) { prm.abortPostback(); } } function getProgress() { PageMethods.GetCurrentProgress($get('Hidden1').value, OnSucceeded,OnFailed); } function adjustProgress(step) { $get('progress_reserve').style.width = (100-step) + "%"; $get('progress_reserve').innerHTML = step+"%"; $get('progress_step').style.width = step + "%"; } function runProcess() { adjustProgress(0); window.setTimeout("getProgress();",1000); $get("Button1").disabled = "disabled"; } </script> </div> <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode= "Conditional"> <ContentTemplate> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" OnClientClick="runProcess()" Text="Run" UseSubmitBehavior= "False" /> <input id="Hidden1" runat="server" type="hidden" /> </ContentTemplate> </asp:UpdatePanel> <br /> <asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1"> <ProgressTemplate> <table cellpadding=0 cellspacing=0 width="100px" height="20px" style="border-width:thin; border-style:solid; border- color:Black" bgcolor="white"> <tr> <td id="progress_step" width="0%" bgcolor=blue></td> <td id="progress_reserve" width="100%" style="color:Black"></td> </tr></table> <br /> <input id="Button2" type="button" value="Cacnel" onclick="cancelProcess()" /> </ProgressTemplate> </asp:UpdateProgress> </form> </body> </html>
讓筆者稍微解釋一下UpdateProgressReport_WithPageMethod.aspx中的設計,這個頁面中放了一個UpdatePanel及一個UpdateProgress控件,UpdatePanel控件中有一個Button控件,當用戶點擊此Button控件后,會先運行OnClientClick所指定的runProcess函數,這個函數會以window.setTimeout定時地調用PageMethods取得最新進度。PageMethods函數調用完畢,OnSucceeded函數會被調用,此處就將進度傳給adjustProgress函數,交由它來調整畫面上的進度顯示。此處有一個小技巧,就是使用了TABLE來做出圖形化的進度行,說來也簡單,只是在一個TABLE中放入一列兩欄,第一欄為當前進度,第二欄為保留進度,依序調整兩欄的寬度就能輕易地做出圖形進度行的效果。眼尖的讀者們應該會查覺到此頁面的UpdateProgress控件中有一個Button是用來取消現行操作的,當用戶點擊該按鈕后,cancelProcess函數會被調用,此處會調用PageMethods中的CancelCurrentProgress函數來通知Server端取消當前操作,之后會取消目前進行中的Async-Postback。是的!這是真正的Async-Postback Cancel功能,比先前只是放棄返回值的做法好多了,圖5-9是此范例的運行畫面。

圖5-9
程序5-13
Samples\5\AdvAjaxDemo\UpdateProgressReport_WithPageMethod.aspx.cs using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class UpdateProgressReport_WithPageMethod : System.Web.UI.Page { [System.Web.Services.WebMethod] public static int GetCurrentProgress(string taskID) { if (HttpRuntime.Cache[taskID] != null) { TaskInformation info = (TaskInformation)HttpRuntime.Cache[taskID]; return info.Progress; } return -1; } [System.Web.Services.WebMethod] public static void CancelCurrentProgress(string taskID) { if (HttpRuntime.Cache[taskID] != null) HttpRuntime.Cache.Remove(taskID); } protected void Page_Load(object sender, EventArgs e) { if (!IsPostback && !ScriptManager1.IsInAsyncPostback) Hidden1.Value = Guid.NewGuid().ToString(); } protected void Button1_Click(object sender, EventArgs e) { TaskInformation info = new TaskInformation(); info.Progress = 0; Cache[Hidden1.Value] = info; for (int i = 0; i < 10; i++) { if (Cache[Hidden1.Value] == null) //cancel break; info.Progress = i * 10; Cache[Hidden1.Value] = info; System.Threading.Thread.Sleep(2000); } Cache.Remove(Hidden1.Value); } } internal class TaskInformation { public int Progress; }
- Practical Data Analysis
- Microsoft Power BI Quick Start Guide
- 高性能混合信號ARM:ADuC7xxx原理與應用開發
- 自動檢測與傳感技術
- 深度學習中的圖像分類與對抗技術
- 完全掌握AutoCAD 2008中文版:綜合篇
- Splunk Operational Intelligence Cookbook
- 新編計算機組裝與維修
- 人工智能趣味入門:光環板程序設計
- Google SketchUp for Game Design:Beginner's Guide
- Web編程基礎
- Apache Spark Quick Start Guide
- 從祖先到算法:加速進化的人類文化
- Keras Reinforcement Learning Projects
- 機器人手工制作