首頁| 新聞| 娛樂| 游戲| 科普| 文學| 編程| 系統| 數據庫| 建站| 學院| 產品| 網管| 維修| 辦公| 熱點
【摘要】在本文中,我將向你展示如何使用asp.net Ajax框架對添加可點擊的熱點的HTML Map控件進行擴展。經擴展后,當我們的鼠標移動到這些熱點上后,即彈出關于這些熱點的詳細信息;但是,這些詳細信息都是通過AJAX異步方式從遠程服務中取得的。
一、 簡介
首先,我們注意到,ASP.NET 2.0中也提供了一個服務器控件ImageMap。此控件是一個讓你可以在圖片上定義熱點(HotSpot)區域的服務器控件。用戶可以通過點擊這些熱點區域進行回發(PostBack)操作或者轉發到某個URL地址。典型情況下,該控件用于需要對某張圖片的局部范圍進行互動操作。然而,這個控件的不足之處在于,在點擊這些熱點區域進行回發時將導致整個Web頁面的刷新。
在本文中,我們將基于ASP.NET AJAX技術對普通的HTML Map控件加以擴展,以達到在點擊其上的熱點區域時,在顯示有關詳細信息時僅僅導致局部的頁面更新,從而使之適應Web 2.0應用程序開發潮流。
下面圖1展示了本文示例程序運行時的一個快照。
圖1.使用AJAX技術擴展后的Map控件熱點點擊僅引發局部更新。
從上圖中看到,當鼠標懸浮于上圖太陽系中的木星(木星)上時,有關該星球的細節信息將以一個彈出窗口形式友好地展示出來(注:此圖取自MSDN,這里沒有翻譯相應單詞)。
二、 創建一個AJAX示例網站
啟動Visual Studio 2005,選擇“文件→新建網站…”,然后選擇“ASP.NET AJAX-Enabled Web Site”模板,命名工程為“Ajax_ImageMap”,并選擇C#作為內置支持語言,最后點擊OK。
然后,添加一個新的ASPX頁面ImageMap.aspx,并且按如下所示修改其中的HTML代碼部分:
在上面代碼中,我們添加了一個HTML 元素和一個HTML 元素(注:VS2005工具欄中沒有提供現成的控件,只能手工添加)。其中定義了各個星球相應的熱點形狀及坐標信息。而且,每一個熱點都有一個相應的onmouseover和onmouseout JavaScript函數與之相關聯。當鼠標在這些熱點上移動時,這兩個函數將被激活,相應信息被顯示出來。有關這兩個函數,我們將在后面詳細討論。
三、 創建一個AJAX服務
現在,我們需要創建一個新的Web服務,由它負責與熱點點擊相關的數據檢索任務。其實,這里所謂的“AJAX服務”,其功能與通常的Web服務是一致的。有關它們之間的細節區別在此不再贅述。現在,你可以右擊工程,然后添加一個命名為LocationService.asmx的Web服務。
注意,在本例中我們僅想通過這個Web服務來模擬實戰環境中的一種簡單邏輯。因此,它僅包含一個Web方法;此方法負責模擬從服務器數據庫中取得客戶端需要的信息。
在此,為了使這個ASP.NET Web服務能夠被從客戶端以AJAX方式加以調用,必須把ScriptService屬性添加到類聲明的前面,如下所示:
以下是引用片段:[ScriptService()] public class LocationService : System.Web.Services.WebService {
現在,編寫我們的Web方法:
以下是引用片段: [WebMethod] [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)] public string GetAreaInfo(string area) { return area; }
根據權威人士建議,為了安全起見,我們一般要使用HttpPost(或者HttpGet= false)方式訪問Web方法。然后,我們把返回的數據格式配置為JSON格式(默認方式即為JSON方式)。
為了簡化起見,這里的GetAreaInfo方法僅僅返回輸入參數的相同值;但在實際開發中,我們應該在此替換以從數據庫中檢索數據。
到目前為止,我們已經成功創建從客戶端以AJAX方式加以調用的Web服務。
但是,我們還要對頁面中的服務器控件ScriptManager進行一些適當的配置,如下所示:
以下是引用片段:<asp:ScriptManager ID="ScriptManager1" runat="server"><services> <asp:servicereference path="~/LocationService.asmx" /></services></asp:ScriptManager>
在此,我們僅在節點下加入了一個服務參考,但其作用如何呢?
從生成的HTML源碼分析,上面的配置將生成如下所示內容:
以下是引用片段:
<script src="LocationService.asmx/jsdebug" type="text/javascript"></script>
這里的腳本標簽引用了一個JavaScript文件LocationService.asmx/jsdebug。其實這是一個Web服務代理類。正是通過此代理類,我們才得以從客戶端以異步方式調用服務器端的Web服務。
更有意思的是,如果你簡單地復制顯示在上面的路徑到瀏覽器中,你將看到一個在運行時刻由AJAX環境生成的JavaScript文件—此文件使腳本服務調用可用。有關代理類,我們不再深入討論。
下面,我們來看如何創建一個定制的客戶端類。
四、 創建客戶端定制類
我們知道ASP.NET AJAX框架的重大“發明”之一就是,它引入了面向對象的JavaScript編程模型。現在,借助于JavaScript設計模式,我們可以輕松地創建自己的模板或類,加入繼承概念,創建接口與枚舉等。
在本文中,我們將開發一個封裝所有本示例中要求功能的客戶端類。
現在,右擊工程,并新添加一個名為ImageMap的JavaScript文件。在此文件中,我們將定義一個新的命名空間MyServices;這個命名空間將包含我們要開發的客戶端類。如下所示:
以下是引用片段:Type.registerNamespace("MyServices");
接下來,我們定義要創建的客戶端類的構造函數:
MyServices.Location = function (uiElement, uiBody) {MyServices.Location.initializeBase(this);this._uiElement = uiElement;this._uiBody = uiBody;this._xAxis = 0;this._yAxis = 0;}
一個模板或類的構造函數也只不過是一個普通的JavaScript函數。該構造器共有兩個參數:uiElement和uiBody。
這兩個參數都將用于描述在頁面顯示的彈出窗口。另外兩個私有變量_xAxis和_yAxis用于描述彈出窗口的顯示位置。典型情況下,我們最好在構造器中聲明所有的私有成員。
接下來,我們將使用原型設計模式編寫該類中的成員函數和屬性:
MyServices.Location.PRototype ={ get_uiElement: function() { return this._uiElement; }, set_uiElement: function(value) { this._uiElement = value; }, get_uiBody: function() { return this._uiBody; }, set_uiBody: function(value) { this._uiBody = value; },
注意,這里的UI元素屬性方法的定義方式非常類似于.NET中各種語言中的定義形式。
下面的成員函數是我們的重點,它負責調用遠程的Web服務:
以下是引用片段: ShowPopupinfo: function(event, areaName){ MyServices.LocationService.GetAreaInfo(areaName, Function.createDelegate(this, this.OnCompleted), this.OnError, //負責進行錯誤處理的回叫函數 this.OnTimeOut); //負責進行超時處理的回叫函數 this._xAxis = event.clientX; this._yAxis = event.clientY;}
上面的代碼展示的是非常典型的從客戶端調用Web服務的方法:
1)形式與調用一個普通的本地方法幾乎一樣方便;
2)Function.createDelegate函數是ASP.NET AJAX客戶端開發中的極為重要的全局函數。創建此函數的原始目的之一是解決this關鍵字的問題。在一個由一個DOM元素引發的事件處理器中,this關鍵字總是引用此DOM元素而不是類本身。但在此,我們使用這個函數的理由是,使得AJAX環境在與激發Web服務的相同的類實例中調用成功時的回叫函數。當你需要引用客戶端類的屬性和方法時,這是相當重要的。簡言之,使用此函數將使得訪問調用Web服務的客戶端類的屬性和方法安全而準確。否則,進行異步調用的客戶端類實例將為null,因為Web服務的響應是在另一個不同的上下文中執行的—這個上下文不再等同于發出異步Web調用請求的那個上下文。
3)有意思的是,這里的GetAreaInfo方法并不是我們在前面創建的Web服務中的那個,而是屬于在運行時刻創建的Web服務代理類—此代理類作為一個客戶端代理訪問服務器端的ASMX Web服務。
上面ShowPopupInfo函數中的最后兩行代碼中,使用事件的輸入參數設置兩個私有變量xAxis和yAxis的值。我們在此的目的是,在與用戶點擊位置盡可能近的地方顯示彈出窗口。
下面是調用成功時對應的回叫函數的實現代碼:
OnCompleted: function(result, userContext, methodName){ var uiElement = $get(this.get_uiElement()); var uiBody = $get(this.get_uiBody()); if (uiBody != null) { var textNode = uiBody.firstChild; if (!textNode) { textNode = document.createTextNode(result); uiBody.appendChild(textNode); } else { textNode.nodeValue = result; } if (uiElement != null) { uiElement.style.visibility = "visible"; uiElement.style.display = "inline"; uiElement.style.left = this._xAxis + "px"; uiElement.style.top = this._yAxis + "px"; } }},
內容相當簡單—把從服務器端返回的數據設置為彈出窗口的顯示內容并根據情況確保顯示此窗口。
在創建客戶端類的最后,我們還必須告訴AJAX框架在客戶端注冊之,以便可以從客戶端訪問它:
以下是引用片段:MyServices.Location.registerClass("MyServices.Location");
至此,客戶端類MyServices.Location已經成功創建。那么,如何使用它呢?
首先,我們需要在頁面加載時定義客戶端類的一個新的實例。為此,我們需要在pageLoad函數中編程:
以下是引用片段: var location = null; function pageLoad(sender, args) { location = new MyServices.Location("modal", "modalBody"); location.HidePopupInfo(); }
上面的代碼簡單地創建MyServices.Location類的一個新的實例。然后調用客戶端類的成員函數之一來隱藏頁面中的彈出窗口。為什么我們在pageLoad函數中創建客戶端類的一個實例呢?原因在于,當AJAX環境控制流程到達pageLoad函數時,所有的AJAX客戶端和用戶定義的JavaScript代碼都已經被成功加載。因此,這一時刻我們可以安全地訪問任何用戶或系統定義的JavaScript代碼。
其它幾個工具函數比較簡單,在此不再贅述。
五、 總結
在本文中,我向你展示了如何通過創建一個AJAX服務和創建自己定制的客戶端類來擴展HTML Map控件。在擴展后的控件中,當點擊圖像中的某個區域時,我們可以通過新型的AJAX方式來給出相關細節信息,而不必刷新整個Web頁面。盡管在大部分Web應用中我們較少應用到這種Map控件(也許因此VS2005工具欄中省略之),但如果開發大量圖片、圖像及地圖操作相關的Web應用時,基于本文AJAX改造后的Map控件一定會讓你的Web應用更加絢爛多彩。
【附】本文源碼調試環境:Windows xp專業版+Visual Studio 2005+ASP.NET AJAX 1.0。
索泰發布一款GTX 1070 Mini迷
AMD新旗艦顯卡輕松干翻NVIDIA
索泰發布一款GTX 1070 Mini迷你版本:小機
芭蕾舞蹈表演,真實美到極致
下午茶時間,悠然自得的休憩
充斥這繁華奢靡氣息的城市迪拜風景圖片
從山間到田野再到大海美麗的自然風景圖片
肉食主義者的最愛美食烤肉圖片
夏日甜心草莓美食圖片
人逢知己千杯少,喝酒搞笑圖集
搞笑試卷,學生惡搞答題
新聞熱點
疑難解答
圖片精選
使用ASP建設私人搜索引擎
華為短消息中心的發展與應用
移動通信計費及客戶服務系統
移動客戶服務中心系統
網友關注