创建定制的ASP.NET AJAX非可视化客户端组件
生活随笔
收集整理的這篇文章主要介紹了
创建定制的ASP.NET AJAX非可视化客户端组件
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、簡介 在本文中,我們將共同討論如何創建一個由基類Sys.Component派生的ASP.NET AJAX非可視化客戶端組件,并將展示它在Web頁面中的用法。 具體說來,你將學習如何實現: ◆使用prototype設計模式以JavaScript定義一個非可視化組件類。
◆把一個非可視化組件注冊為一個由基類Component派生的類。
◆初始化該非可視化組件的基類—Component,并調用它的方法。
◆創建能夠激發一個更改通知的屬性。
◆打造一個完整的Demo.Timer非可視化組件。
◆在一個Web頁面中使用該組件,并且綁定到它的事件。 注意,在ASP.NET AJAX 1.0框架中構建客戶端組件,除了本文中介紹的方法(這些組件派生自Component)外,還存在另外兩種類型的擴展基本組件功能的ASP.NET AJAX客戶端組件對象:派生自Sys.UI.Behavior的Behavior和派生自Sys.UI.Control的Control。下列表格概括 了Component,Behavior和Control之間的區別。 ? 另外,為了運行本文中的示例,你需要具備下列條件: ◆一個測試網站;
◆安裝微軟ASP.NET AJAX 1.0框架,在此不再贅述。 二、非可視化客戶端組件的基本功能 一個ASP.NET AJAX非可視化客戶端組件對將重用于應用程序中的JavaScript代碼加以封裝。非可視化組件的一個典型的示例是一個每隔一定時間激發事件的定時器組件。 通過派生于Component基類,你的定制組件能夠自動地繼承其中的許多特征,具體包括: ◆一個跨瀏覽器模型—用于管理綁定到客戶端對象事件的處理器。
◆在客戶端應用程序中把該組件自動注冊為一個實現了Sys.IDisposable接口的可釋放的對象。
◆當屬性改變時激發通知事件。
◆實現組件屬性設置的批處理,這比通過單個屬性的get和set訪問器來處理所有的邏輯更為有效(在腳本大小和處理時間方面)。
◆重載Sys.UI.Control.initialize方法以便初始化所有屬性和事件監聽器。 三、實現一個派生自Component的客戶端組件 下面的列表概括了實現一個派生自Component的定制客戶端組件需要的步驟。后面,我們將作詳細分析。 ◆使用prototype設計模式定義一個組件類。
◆初始化該組件的基組件實例。
◆暴露所有的屬性訪問器,并且選擇性地激發一個propertyChanged通知事件。
◆重載dispose方法以便釋放資源,例如clearing事件處理器。 (一)使用Prototype設計模式定義一個組件類 一個ASP.NET AJAX客戶端類(它包括一個組件類)通過JavaScript使用prototype設計模式進行定義。下面的列表歸納了使用prototype設計模式定義一個組件類所需要的步驟: ◆注冊你的組件類的命名空間。
◆創建該組件的構造器函數,并且在該構造器函數中定義任何的private字段,同時設置它們的初始值。
◆使用prototype設計模式定義該組件的原型。
◆把該組件函數注冊為一個派生自Component的類。 (二)初始化基類 任何派生自一個基組件類(例如組件,控件,或行為)的組件類都必須在其構造器中初始化它的基類。這使該基類對象能夠執行初始化任務—例如把該組件注冊為一個可釋放的對象—使用Sys.Application實例。 在該組件的構造器函數中,你可以調用繼承的Type.initializeBase方法,—典型地,是在該構造器中的任何其它代碼運行之前進行。該 initializeBase方法初始化一個注冊類的基類型。一個非可視化組件類被注冊為一個類—擁有一個Component基類型。當該 Component基類被初始化時,它的方法可用于該組件中,并且它會把該組件自動地注冊為ASP.NET AJAX應用程序中一個可釋放的對象。 下列示例展示了一個派生自Component的非可視化組件的構造器函數。該構造器調用了它繼承的initializeBase方法。
(三)定義屬性并激發propertyChanged通知 通常情況下,你在希望頁面開發者綁定到的組件的類中進行屬性定義。另外,你還可以選擇從你的組件的屬性中激發propertyChanged通知事 件。然后,使用你的組件頁面開發者就可以綁定到這些事件上。一個派生自Component,Behavior或Control的ASP.NET AJAX組件繼承該raisePropertyChanged方法,調用此方法將激發一個propertyChanged事件。 (四)初始化屬性和事件監聽器 如果你的定制組件必須初始化任何屬性或事件監聽器的話,那么,你可以在該組件的原型中重載Sys.UI.Control.initialize方 法。例如,一個派生自Component的非可視化組件可能會一個委托委托給一個事件—例如Window.onFocus。典型地,一個派生自 Control基類的客戶端控件會把任何代理綁定到它的DOM元素事件上,并且把這些DOM元素屬性設置為初始值。最后一步,你需要調用基類的 initialize方法以便使組件的基類最終完成初始化。 (五)釋放資源 如果在釋放該組件之前你的定制組件必須釋放資源,那么,你需要重載dispose方法,在該重載方法中釋放該資源。這可以確保在釋放該組件前立即釋 放該資源。應該釋放的資源可能包括用于綁定到DOM事件的代理。通過確保去除存在于DOM元素與該組件對象之間的循環參考,你可以使該對象徹底從內存中刪 除。 四、在Web頁面中應用非可視化組件 為了在一個ASP.NET AJAX應用程序頁面中使用前面創建的定制客戶端組件,你需要下列步驟: ◆在Web頁面中注冊該組件的腳本庫。
◆創建一個組件實例。 下面我們來詳細討論這些步驟。 (一)在Web頁面中注冊組件的腳本庫 我們可以通過聲明方式或編程方法通過一個ScriptManager控件來注冊在頁面中使用一個客戶端控件所需要的腳本。 【注意】客戶端組件可以受托管于一個實現了IScriptControl接口的定制服務器控件。這樣的一個定制服務器控件可以自動地注冊要求的組件腳本并且暴露設置組件屬性和事件綁定的聲明性標記。這樣將使得頁面開發者更容易使用此客戶端組件。 下面的示例展示了一個注冊組件腳本的ScriptManager控件的聲明性標記:
在此,元素的 【特別注意】所有要使用ScriptManager控件進行注冊的腳本文件都必須調用notifyScriptLoaded方法以通知應用程序該腳本已經加載完畢。大多數情況下,嵌入式于一個程序集內的腳本不應該調用這個方法。 (二)創建定制組件實例 你可以通過調用Sys.Component.create方法(或$create快捷方式)來實例化一個客戶端組件。為此,你需要把相應的參數傳遞 到$create方法以指定該組件的類型。你還要傳遞一個JSON對象,這個JSON對象用于包含一個要求的ID值以及可選的初始屬性值和事件處理器綁 定。 下面這個示例展示了如何通過調用$create方法來實例化一個組件實例。
五、打造定制的Demo.Timer組件 從現在開始,我們來創建一個名字為Demo.Timer的定制客戶端組件,然后把它應用于一個Web頁面中。這里的Demo.Timer是一個簡單 的定時器組件,它能夠根據interval屬性激發一個propertyChanged事件,并暴露一個enabled屬性,還定義了一個tick事件。 使用這個Demo.Timer組件的頁面開發者可以綁定到propertyChanged事件并且在每次更新interval屬性時采取自己的行動。當 然,開發者還可以處理tick事件。 為了創建該Demo.Timer組件的代碼,我們需要: 1.在ASP.NET AJAX應用程序的目錄下創建一個名字為DemoTimer.js的文件。
2.然后,把下列JavaScript代碼添加到該文件中:
【注】上面的JavaScript腳本集中體現了ASP.NET AJAX 1.0框架對于客戶端JavaScript編程進行的簡化。很顯然,這里仍然基于JavaScript腳本語言中的prototype模型,但已對之進行了面向對象的進一步包裝。 上面的代碼首先通過調用Type.registerNamespace方法實現注冊Demo命名空間。ASP.NET AJAX開發小組建議,最好在構造器中聲明和初始化所有的private域,例如在這個示例中初始化了interval域。接下來,構造器調用繼承的 initializeBase方法,以便使用基類Component中的方法。然后,被初始化的基類使用客戶端應用程序把此Demo.Timer實例注冊 為一個可釋放的對象。 在這個prototype中,聲明并初始化private域(例如interval)。在此,這個prototype定義了兩個public屬性: interval和enabled;還定義了針對每一個屬性的get和set訪問器方法。在每一個public屬性的set訪問器方法中,通過調用 propertyChanged方法激活一個propertyChanged事件。這樣以來,每次改變此屬性時,頁面開發者都會得到通知。 上面的add_tick和remove_tick方法支持頁面開發者添加和刪除監聽tick事件的委托處理器。這些方法通過該組件的事件處理器集合 來添加或刪除指定的處理器。你可以通過組件的Sys.EventHandlerList對象來添加和刪除你的組件類中的委托處理器。 EventHandlerList對象包含一個該組件的事件處理器的集合—通過繼承的Sys.Component.events屬性實現。在本示例中,該 代碼調用返回的EventHandlerList對象的Sys.EventHandlerList.addHandler和 Sys.EventHandlerList.removeHandler方法,以便為了添加或刪除指定的處理器。 這個Demo.Timer類重載了基類的dispose方法以便更新enabled屬性并且向開發人員指示此組件已經被禁用。通過enabled屬 性的set訪問器可以激發propertyChanged事件以便發送通知。然后,調用private型_stopTimer方法以停止激發tick事 件。最后,調用基類中的dispose方法來支持應用程序釋放掉該組件。 六、在Web頁面中應用Demo.Timer組件 在一個頁面中的客戶端組件實例可以托管給一個服務器控件或由Web頁面中的客戶端腳本所使用。現在,我們來討論如何創建一個組件實例—通過在Web頁面中使用客戶端腳本的方式。 啟動Visual Studio 2005,選擇“文件→新建網站…”,然后選擇“ASP.NET AJAX-Enabled Web Site”模板,命名工程為“NoVisComponentTest”,并選擇C#作為編程語言,最后點擊OK。 把文件名Default.aspx更改為DemoTimer.aspx。然后,把該文件源碼內容修改為:
相應于DemoTimer.aspx頁面的設計時刻快照如下圖1所示:
在該示例頁面中,在元素中定義了兩個函數。其中,OnTick函數是一個將被綁定到Demo.Timer組件的tick事件的委托。這個OnTick函數負責處理tick事件并更新位于一個HTML元素中的計數器值。 在applicationLoadHandler事件處理器中,Demo.Timer組件在客戶端腳本中被實例化—通過調用$Create方法并傳遞如下參數實現: ◆第一個類型參數被指定為你在前面創建的Demo.Timer類;
◆屬性參數中包含了一個JSON對象—包含要求的組件ID值,后面跟著一 些可選的屬性名字值對,用于指定屬性的初始值。其中,interval屬性被初始設置為2000毫秒;這樣,每隔2秒定時器就會激發一個tick事件。該 組件的enabled屬性被置為true;這樣以來,一旦實例化它后,就立即啟動它。
◆最后的可選事件參數中包含一個對象,該對象提供了與其初始事件處理器代理相匹配的事件名稱。在本文示例中,該tick事件被委托給一個初始的onTick委托(定義于頁面的元素中)。 此外,在前面的ScriptManager控件中,結點的path屬性參考定義Demo.Timer組件類的DemoTimer.js文件的路徑。 【注意】由于新框架對于客戶端JavaScript編程作了較大規模調整,所以請讀者詳細研究上面源碼中的代碼結構。
下圖2展示了示例網頁運行時刻快照。
注意到:每隔2秒鐘,定時器就會激發一個tick事件,紅色計數值加1。 七、總結 從本文中,我們看到,ASP.NET AJAX 1.0框架并不僅僅對AJAX編程中的構建客戶端進行了簡化,還提供了簡化的面向對象JavaScript模型,從而有助于開發人員進一步開發出屬于自己 的客戶端定制組件。除了本文中介紹的方法(這些組件派生自Component)外,還存在另外兩種類型的擴展基本組件功能的ASP.NET AJAX客戶端組件對象:派生自Sys.UI.Behavior的Behavior和派生自Sys.UI.Control的Control。 ASP.NET AJAX 1.0框架幫助文檔中提供了相應的示例,在此不再贅述。
本文轉自朱先忠老師51CTO博客,原文鏈接:http://blog.51cto.com/zhuxianzhong/59829?,如需轉載請自行聯系原作者
新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!
◆把一個非可視化組件注冊為一個由基類Component派生的類。
◆初始化該非可視化組件的基類—Component,并調用它的方法。
◆創建能夠激發一個更改通知的屬性。
◆打造一個完整的Demo.Timer非可視化組件。
◆在一個Web頁面中使用該組件,并且綁定到它的事件。 注意,在ASP.NET AJAX 1.0框架中構建客戶端組件,除了本文中介紹的方法(這些組件派生自Component)外,還存在另外兩種類型的擴展基本組件功能的ASP.NET AJAX客戶端組件對象:派生自Sys.UI.Behavior的Behavior和派生自Sys.UI.Control的Control。下列表格概括 了Component,Behavior和Control之間的區別。 ? 另外,為了運行本文中的示例,你需要具備下列條件: ◆一個測試網站;
◆安裝微軟ASP.NET AJAX 1.0框架,在此不再贅述。 二、非可視化客戶端組件的基本功能 一個ASP.NET AJAX非可視化客戶端組件對將重用于應用程序中的JavaScript代碼加以封裝。非可視化組件的一個典型的示例是一個每隔一定時間激發事件的定時器組件。 通過派生于Component基類,你的定制組件能夠自動地繼承其中的許多特征,具體包括: ◆一個跨瀏覽器模型—用于管理綁定到客戶端對象事件的處理器。
◆在客戶端應用程序中把該組件自動注冊為一個實現了Sys.IDisposable接口的可釋放的對象。
◆當屬性改變時激發通知事件。
◆實現組件屬性設置的批處理,這比通過單個屬性的get和set訪問器來處理所有的邏輯更為有效(在腳本大小和處理時間方面)。
◆重載Sys.UI.Control.initialize方法以便初始化所有屬性和事件監聽器。 三、實現一個派生自Component的客戶端組件 下面的列表概括了實現一個派生自Component的定制客戶端組件需要的步驟。后面,我們將作詳細分析。 ◆使用prototype設計模式定義一個組件類。
◆初始化該組件的基組件實例。
◆暴露所有的屬性訪問器,并且選擇性地激發一個propertyChanged通知事件。
◆重載dispose方法以便釋放資源,例如clearing事件處理器。 (一)使用Prototype設計模式定義一個組件類 一個ASP.NET AJAX客戶端類(它包括一個組件類)通過JavaScript使用prototype設計模式進行定義。下面的列表歸納了使用prototype設計模式定義一個組件類所需要的步驟: ◆注冊你的組件類的命名空間。
◆創建該組件的構造器函數,并且在該構造器函數中定義任何的private字段,同時設置它們的初始值。
◆使用prototype設計模式定義該組件的原型。
◆把該組件函數注冊為一個派生自Component的類。 (二)初始化基類 任何派生自一個基組件類(例如組件,控件,或行為)的組件類都必須在其構造器中初始化它的基類。這使該基類對象能夠執行初始化任務—例如把該組件注冊為一個可釋放的對象—使用Sys.Application實例。 在該組件的構造器函數中,你可以調用繼承的Type.initializeBase方法,—典型地,是在該構造器中的任何其它代碼運行之前進行。該 initializeBase方法初始化一個注冊類的基類型。一個非可視化組件類被注冊為一個類—擁有一個Component基類型。當該 Component基類被初始化時,它的方法可用于該組件中,并且它會把該組件自動地注冊為ASP.NET AJAX應用程序中一個可釋放的對象。 下列示例展示了一個派生自Component的非可視化組件的構造器函數。該構造器調用了它繼承的initializeBase方法。
| Samples.SimpleComponent = function() { Samples.SimpleComponent.initializeBase(this); } |
◆創建一個組件實例。 下面我們來詳細討論這些步驟。 (一)在Web頁面中注冊組件的腳本庫 我們可以通過聲明方式或編程方法通過一個ScriptManager控件來注冊在頁面中使用一個客戶端控件所需要的腳本。 【注意】客戶端組件可以受托管于一個實現了IScriptControl接口的定制服務器控件。這樣的一個定制服務器控件可以自動地注冊要求的組件腳本并且暴露設置組件屬性和事件綁定的聲明性標記。這樣將使得頁面開發者更容易使用此客戶端組件。 下面的示例展示了一個注冊組件腳本的ScriptManager控件的聲明性標記:
| <form id="form1" runat="server"> <asp:ScriptManager runat="server" ID="ScriptManager01"> <scripts> <asp:ScriptReference path="DemoTimer.js" /> </scripts> </asp:ScriptManager> </form> |
| function pageLoad() { $create(Demo.Timer, {enabled:true,id:"demoTimer1", interval:2000}, {tick:OnTick}, null); } |
2.然后,把下列JavaScript代碼添加到該文件中:
| Type.registerNamespace("Demo"); Demo.Timer = function() { Demo.Timer.initializeBase(this); this._interval = 1000; this._enabled = false; this._timer = null; } Demo.Timer.prototype = { //聲明該prototype中的值類型 get_interval: function() { /// 以毫秒為單位的時間間隔值 return this._interval; }, set_interval: function(value) { if (this._interval !== value) { this._interval = value; this.raisePropertyChanged('interval'); if (!this.get_isUpdating() && (this._timer !== null)) { this._restartTimer(); } } }, get_enabled: function() { /// 當啟動定時器時為True;否則為false。 return this._enabled; }, set_enabled: function(value) { if (value !== this.get_enabled()) { this._enabled = value; this.raisePropertyChanged('enabled'); if (!this.get_isUpdating()) { if (value) { this._startTimer(); } else { this._stopTimer(); } } } }, //事件 add_tick: function(handler) { /// 增加一個相應于tick事件的事件處理器 /// 添加事件的處理器 this.get_events().addHandler("tick", handler); }, remove_tick: function(handler) { ///刪除tick事件的一個事件處理器 ///?刪除事件的處理器 this.get_events().removeHandler("tick", handler); }, dispose: function() { //調用set_enabled以便激發屬性改變事件 this.set_enabled(false); //保證的確停止了,這樣在釋放后就不必調用了 this._stopTimer(); //確保調用base.dispose() Demo.Timer.callBaseMethod(this, 'dispose'); }, updated: function() { Demo.Timer.callBaseMethod(this, 'updated'); //在批更新(this.beginUpdate(), this.endUpdate())后調用 if (this._enabled) { this._restartTimer(); } }, _timerCallback: function() { var handler = this.get_events().getHandler("tick"); if (handler) { handler(this, Sys.EventArgs.Empty); } }, _restartTimer: function() { this._stopTimer(); this._startTimer(); }, _startTimer: function() { //保存定時器cookie便于以后刪除之用 this._timer = window.setInterval(Function.createDelegate(this, this._timerCallback), this._interval); }, _stopTimer: function() { if(this._timer) { window.clearInterval(this._timer); this._timer = null; } } } //描述這個組件所有的屬性、事件和方法的JSON對象。 //注意,此組件應該能夠通過Sys.TypeDescriptor方法和通過xml-script進行尋址。 Demo.Timer.descriptor = { properties: [?? {name: 'interval', type: Number}, {name: 'enabled', type: Boolean} ], events: [ {name: 'tick'} ] } Demo.Timer.registerClass('Demo.Timer', Sys.Component); //既然這個腳本不是通過System.Web.Handlers.ScriptResourceHandler //加載的,所以,我們在此調用 // Sys.Application.notifyScriptLoaded來通知ScriptManager。 //這是腳本的結束處,根據前面的揭示,這一句必須有 if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded(); |
| <%@ Page Language="C#" %> <%@ Register Assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Namespace="System.Web.UI" TagPrefix="asp" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "[url]http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd[/url]"> <html xmlns="[url]http://www.w3.org/1999/xhtml[/url]"> <head id="Head1" runat="server"> <title>ASP.NET AJAX客戶端非可視化組件編程測試</title> </head> <body> <form id="form1" runat="server"> <div> <br /> <h1> <span style="color: #000099">【ASP.NET AJAX客戶端非可視化組件編程測試】</span><br /> </h1> <asp:ScriptManager id="ScriptManager1" runat="server" > <Scripts> <asp:ScriptReference Path="DemoTimer.js" /> </Scripts> </asp:ScriptManager> <span style="font-size: 32pt"> 定時器開始計數: <span style="color: #ff3333"><strong> <span id="result">0</span> </strong></span></span> </div> <script type="text/javascript"> ???? function OnTick(sender, args) { var result = $get("result"); result.innerText = parseInt(result.innerText) + 1; } ????? var app = Sys.Application; app.add_load(applicationLoadHandler); function applicationLoadHandler(sender, args) { //創建DemoTimer組件實例。 //設置屬性并綁定事件。 $create(Demo.Timer, {enabled:true,id:"demoTimer1",interval:2000}, {tick:OnTick}, null, null); } </script> </form> </body> </html> |
| 圖1:示例網頁的設計時刻快照 |
◆屬性參數中包含了一個JSON對象—包含要求的組件ID值,后面跟著一 些可選的屬性名字值對,用于指定屬性的初始值。其中,interval屬性被初始設置為2000毫秒;這樣,每隔2秒定時器就會激發一個tick事件。該 組件的enabled屬性被置為true;這樣以來,一旦實例化它后,就立即啟動它。
◆最后的可選事件參數中包含一個對象,該對象提供了與其初始事件處理器代理相匹配的事件名稱。在本文示例中,該tick事件被委托給一個初始的onTick委托(定義于頁面的元素中)。 此外,在前面的ScriptManager控件中,結點的path屬性參考定義Demo.Timer組件類的DemoTimer.js文件的路徑。 【注意】由于新框架對于客戶端JavaScript編程作了較大規模調整,所以請讀者詳細研究上面源碼中的代碼結構。
下圖2展示了示例網頁運行時刻快照。
| 圖2:示例網頁運行時刻快照 |
本文轉自朱先忠老師51CTO博客,原文鏈接:http://blog.51cto.com/zhuxianzhong/59829?,如需轉載請自行聯系原作者
新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!
總結
以上是生活随笔為你收集整理的创建定制的ASP.NET AJAX非可视化客户端组件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TCP/IP学习(30)——L2数据链路
- 下一篇: Oracle 安装时候的fs.aio-m