官术网_书友最值得收藏!

  • 決戰.NET
  • 黃忠成
  • 805字
  • 2018-12-27 16:56:05

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是此范例的運行畫面。

true

圖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;
    }
主站蜘蛛池模板: 彰化县| 孟津县| 涟源市| 柯坪县| 鄂托克旗| 松桃| 北海市| 西峡县| 石林| 台州市| 大关县| 南投县| 社旗县| 清远市| 台北县| 和龙市| 阳朔县| 金秀| 疏勒县| 陇西县| 科技| 尚志市| 集贤县| 交口县| 长治市| 山阳县| 赣州市| 佛山市| 刚察县| 阿坝县| 青川县| 青神县| 游戏| 泗洪县| 伊通| 绵竹市| 灵山县| 卢湾区| 台南市| 安陆市| 双城市|