【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件

iDotNetSpace發表於2008-06-11

當後臺在進行某些長時間的操作時,如果能在頁面上提供一個顯示真實進度的進度條,而不是讓使用者不知情的等待或是從前的那些簡單的估計,將是一個非常難得的出彩之處。現在使用ASP.NET Atlas完全有可能做到這些。這篇文章將討論如何完成這一功能並介紹一些有關Atlas客戶端控制元件開發的基本概念。您同時可以在這裡下載示例程式以及原始檔

實現網頁上的進度條想法其實很簡單:編寫一個客戶端的Atlas控制元件,每隔一段時間請求一次伺服器,並使用返回的當前進度資料更新進度條的顯示。在這個示例中,將有四個部分的程式碼組成:

  1. 一個需要較長時間才能完成的Web Service
  2. 一個用來查詢上述Web Service進度的Web Service
  3. 客戶端Atlas進度條(ProgressBar)控制元件,負責維護客戶端邏輯並輸出視覺化UI。這也是本示例中最重要的一個元件,在將來可被重用於其他頁面或程式的開發
  4. 包含上述Web Service以及控制元件的ASP.NET測試頁面

下面我們一步一步地來實現以上四個步驟:

 需要較長時間完成的Web Service

在實際的程式中,一個需要較長時間完成的Web Service可能有如下宣告:

1【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件[WebMethod]
2【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件public void TimeConsumingTask()
3【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件{
4【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    ConnectToDataBase();
5【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    GetSomeValueFromDataBase();
6【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    CopySomeFilesFromDisk();
7【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    GetARemoteFile();
8【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

這樣我們就可以插入一些輔助方法來確定當前進度完成情況,setProgress(int)用來設定當前的進度完成百分比:

 1【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件[WebMethod]
 2【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件public void TimeConsumingTask()
 3【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件{
 4【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    setProgress(0);
 5【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    ConnectToDataBase();
 6【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    setProgress(10);
 7【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    GetSomeValueFromDataBase();
 8【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    setProgress(40);
 9【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    CopySomeFilesFromDisk();
10【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    setProgress(50);
11【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    GetARemoteFile();
12【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    setProgress(100);
13【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

在本示例中,我們僅僅使用Cache來儲存進度完成資訊並利用Thread.Sleep()方法模擬操作的延遲:

 1【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件[WebMethod]
 2【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件public int StartTimeConsumingTask()
 3【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件{
 4【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    string processKey = this.Context.Request.UserHostAddress;
 5【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    string threadLockKey = "thread" + this.Context.Request.UserHostAddress;
 6【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    object threadLock = this.Context.Cache[threadLockKey];
 7【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    if (threadLock == null)
 8【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    {
 9【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        threadLock = new object();
10【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        this.Context.Cache[threadLockKey] = threadLock;
11【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    }

12【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
13【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    // Only allow 1 running task per user.
14【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    if (!Monitor.TryEnter(threadLock, 0))
15【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        return -1;
16【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
17【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    DateTime startTime = DateTime.Now;
18【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
19【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    // Simulate a time-consuming task.
20【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    for (int i = 1; i <= 100; i++)
21【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    {
22【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        // Update the progress for this task.
23【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        this.Context.Cache[processKey] = i;
24【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        Thread.Sleep(70);
25【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    }

26【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
27【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    Monitor.Exit(threadLock);
28【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
29【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    return (DateTime.Now - startTime).Seconds;
30【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

31【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件

 

查詢進度的Web Service

很容易實現,只需從Cache中取得進度資訊:

 1【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件[WebMethod]
 2【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件public int GetProgress()
 3【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件{
 4【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    string processKey = this.Context.Request.UserHostAddress;
 5【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    object progress = this.Context.Cache[processKey];
 6【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    if (progress != null)
 7【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    {
 8【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        return (int)progress;
 9【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    }

10【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
11【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    return 0;
12【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

 

客戶端進度條(ProgressBar)控制元件

第一步:從Sys.UI.Control繼承

ProgressBar控制元件應該繼承自Atlas的控制元件基類Sys.UI.Control,並且宣告為密封類(sealed class,不能再被繼承)。Sys.UI.Control基類包含了一些所有的控制元件共有的操作與方法。比如,將自己與某個HTML元素關聯起來(也就是所謂的binding)等。同時也要註冊以讓Atlas瞭解這個新的型別以便今後的宣告及使用,例如,讓Atlas可以取得這個型別的描述等。

1【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件Sys.UI.ProgressBar = function(associatedElement) {
2【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    Sys.UI.ProgressBar.initializeBase(this, [associatedElement]);
3【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
4【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

5【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件Type.registerSealedClass('Sys.UI.ProgressBar', Sys.UI.Control);
6【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件Sys.TypeDescriptor.addType('script','progressBar', Sys.UI.ProgressBar);
7【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件

 

第二步:新增私有成員並書寫相應的Setter/Getter

下面需要新增一些屬性用來設定我們的控制元件。在這個例子中,我們需要三個屬性:

  1. Interval. 每次重新查詢進度並更新進度條的間隔時間。單位:毫秒
  2. Service Url. Web Service檔案的路徑。
  3. Service Method. 取得進度資訊的方法名。

這些屬性應該嚴格遵守Atlas的命名規範:Getter應該以'get_'開頭,Setter應該以'set_'開頭並傳入一個引數。還需要在控制元件的描述方法(descriptor)中新增對於這些屬性的說明。有關描述方法(descriptor)將在第四步中說明。例如,針對Service Method屬性,我們有如下宣告:

1【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件var _serviceMethod;
2【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
3【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件this.get_serviceMethod = function() {
4【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    return _serviceMethod;
5【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

6【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
7【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件this.set_serviceMethod = function(value) {
8【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    _serviceMethod = value;
9【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

 

第三步:使用Timer控制元件每隔一段時間查詢一次Web Service

Sys.Timer用於每過一段時間呼叫一個方法(發出一個事件),我們可以定義一個委託來指向這個方法,並在並在每一個時間段內查詢這個Web Service。為了避免瀏覽器記憶體洩露,在控制元件析構(dispose)的時候應該記得做一些必要的清理。

還有,注意當前一個請求並沒有返回時,不應該傳送第二個請求。

 1【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件var _timer = new Sys.Timer();
 2【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件var _responsePending;
 3【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件var _tickHandler;
 4【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件var _obj = this;
 5【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
 6【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件this.initialize = function() {
 7【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    Sys.UI.ProgressBar.callBaseMethod(this, 'initialize');
 8【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    _tickHandler = Function.createDelegate(thisthis._onTimerTick);
 9【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    _timer.tick.add(_tickHandler);
10【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    this.set_progress(0);
11【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

12【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
13【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件this.dispose = function() {
14【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    if (_timer) {
15【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        _timer.tick.remove(_tickHandler);
16【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        _tickHandler = null;
17【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        _timer.dispose();
18【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    }

19【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    _timer = null;
20【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    associatedElement = null;
21【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    _obj = null;
22【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
23【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    Sys.UI.ProgressBar.callBaseMethod(this, 'dispose');
24【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

25【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
26【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件this._onTimerTick = function(sender, eventArgs) {
27【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    if (!_responsePending) {
28【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        _responsePending = true;
29【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        
30【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        // Asynchronously call the service method.
31【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件        Sys.Net.ServiceMethod.invoke(_serviceURL, _serviceMethod, nullnull, _onMethodComplete);
32【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    }

33【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

34【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
35【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件function _onMethodComplete(result) {
36【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    // Update the progress bar.
37【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    _obj.set_progress(result);
38【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    _responsePending = false;
39【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

 

第四步:新增控制方法

我們應該可以控制進度條的開始/停止。並且,對於一個Atlas控制元件,相關的描述方法(descriptor)也是必須的。Atlas會利用它來描述這個型別的資訊。

 1【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件this.getDescriptor = function() {
 2【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    var td = Sys.UI.ProgressBar.callBaseMethod(this, 'getDescriptor');
 3【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    td.addProperty('interval', Number);
 4【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    td.addProperty('progress', Number);
 5【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    td.addProperty('serviceURL', String);
 6【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    td.addProperty('serviceMethod', String);
 7【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    td.addMethod('start');
 8【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    td.addMethod('stop');
 9【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    return td;
10【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

11【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
12【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件this.start = function() {
13【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    _timer.set_enabled(true);
14【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

15【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件
16【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件this.stop = function() {
17【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    _timer.set_enabled(false);
18【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件}

 

OK,目前為止客戶端的控制元件就完成了。我們把它存為ProgressBar.js

ASP.NET Testing Page ASP.NET測試頁面

對於任何的Atlas頁面,我們第一件需要做的事情就是新增一個ScriptManager伺服器控制元件。在這個示例中我們將引用ProgressBar控制元件,較長時間才能完成的Web Service以及進度查詢Web Service。(這兩個Web Service位於同一個檔案中:TaskService.asmx

1【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件<atlas:ScriptManager ID="ScriptManager1" runat="server" >
2【Dflying Chen 】使用ASP.NET Atlas編寫顯示真實進度的ProgressBar(進度條)控制元件    <

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-343352/,如需轉載,請註明出處,否則將追究法律責任。

相關文章