ASP.NET 2.0+Atlas编写鼠标拖放程序(2)
生活随笔
收集整理的這篇文章主要介紹了
ASP.NET 2.0+Atlas编写鼠标拖放程序(2)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
摘要 本文將詳細探討Atlas中的聲明性編程與強制性編程之間的關系,及如何用之在一個web客戶端實現拖放功能。下圖為本文相應示例程序運行結果快照。
運行結果
一. 簡介
本文旨在幫助讀者理解微軟的Atlas技術的某些方面的工作原理。Atlas的實現宗旨是簡化AJAX風格的Web程序開發。然而,就象所有其它技術一樣,為了更好地使用這個工具,你需要深入理解Atlas抽象的內在技術。Atlas抽象的一個關鍵之處是新的XML標記語法,目的是實現利用Atlas進行編程更為容易。借助于XML標記,開發者能夠以聲明性方式修改他們的代碼。然而,有時當一個開發者可能想以編程方式來改變其代碼時,他需要理解,在標記抽象層下面,他實際在與一些JavaScript及一些微軟開發的定制JavaScript庫打交道。為了展示Atlas聲明性模型與可編程模型之間的關系,我們將討論幾個例子,在這些示例中,我們將使用兩種模型來實現相同的功能。我將向你展示如何使用AtlasUIDragDrop庫文件來執行基本的拖放操作以及建立放置區。
[背景]
當我寫作本文時,Atlas仍處于其beta測試階段,并且在繼續修改中。本文中的這些示例適用于Atlas的四月CTP版本;因此,Atlas的更新的發行版本可能會影響本文的精確性。另外,還要注意,Atlas僅能與.NET 2.0一起工作。
二. 聲明性拖放
為了把拖放行為添加到一個div標簽,第一項任務是使用Atlas標記。通過拖放,我僅想實現能夠拖放一個對象并且讓它位于你想把它放置的地方。當把一個對象放置到一個指定的點時,在實際開發中所表現出的動作將在后面討論。為了配置你的網頁以便使用Atlas,你需要從微軟站點把Microsoft.Web.Atlas.dll文件下載到你的bin文件夾下并且使用下列入口配置你的web.config文件:
接下來,你需要把一個Atlas腳本管理器控件添加到你的.aspx頁面并且使用AtlasUIDragDrop庫來配置:
然后,添加你想使之可拖放的div對象,并且確保它有一個拖放句柄:
最后,添加能夠使你的div成為可拖放的標記腳本:
至此,你應該有了一個可拖放的div標簽。該示例展示了結合Atlas使用聲明性方式的簡單性和容易性。在Atlas所引入的術語中,你僅使用了聲明性標記來把漂浮行為添加到一個HTML元素。 三. 強制性拖放
為了使用編程方式來實現相同的功能,我們需要進行一些編程,但是不需要較多的編碼。你必須明白,當你把一個Atlas腳本管理器組件添加到你的頁面上時,你實際上是在下命令把Atlas JavaScript庫加載到你的頁面。這個Atlas庫提供了擴展DOM的客戶端類,并且提供允許你在一個瀏覽器中進行編碼的工具(盡管現在在Safari兼容性方面還存在一些問題)。這些客戶端類還允許你把你的HTML元素添加到行為。
為了切換到一個強制性模型,你需要用兩個JavaScript函數來代替XML標記。第一個函數是一個普通腳本用于把漂浮行為添加到一個HTML元素上。它利用了Atlas客戶端類來完成此功能:
這個函數使用兩個參數值:你想要拖放的HTML元素和實現該拖放行為的拖放句柄HTML元素。然后,你實例化一個新的Atlas客戶端行為對象。該漂浮行為具有一個handle屬性-你把HTML元素的句柄傳遞給它。然后,你需要基于你想使之成為可拖放的控件以創建一個新的客戶端控件對象。把你的div標簽轉換成一個Atlas客戶端控件能夠使你把Atlas行為添加到它上面。你可以使用get_behaviors()方法來返回一個行為集合,并且使用add方法來把一個新行為添加到你的HTML對象。最后,你調用行為對象的initialize()方法以允許在內部配置行為自身。我們將在本文剩下的部分中一直使用這個工具函數。
現在,當頁面裝載時,你需要調用addFloatingBehavior函數。說實話,這是編寫這個示例中最有難度的編碼部分。腳本管理器并不是簡單地創建一個到Atlas JavaScript庫的引用,我推想它實際把該庫腳本裝載到DOM。在任何情況下,這意味著,只有頁面中的其它一切都裝載后該庫才得到加載。這樣以來,我們所面臨的問題在于,裝載該庫后,沒有標準的方法來使我們的添加漂浮行為的代碼運行;并且如果我們在加載該庫前運行它,那么我們可以簡單地生成JavaScript錯誤-因為我們調用的所有的Atlas方法都不能被發現。
其實,存在好幾種方法可以來解決這個問題,但是最容易的方法是使用一個定制的Atlas事件pageLoad()-這個事件實際只在裝載這些庫后才調用它。為了把漂浮行為添加到你的div標簽中,當第一次加載頁面時(但是在庫腳本裝載后),你僅需要編寫如下代碼:
這可以使用一種Atlas腳本速記方式來書寫-用"$()"代替"document.getElementById()":
在此,可以看到,你有一個可拖動的div,其行為與你使用聲明性模型編寫的可拖動的div完全一致。
四. 動態拖放
既然聲明性模型比強制性模型更為清晰,那么為什么你還要編寫自己的JavaScript來處理Atlas行為呢?其實,這種聲明性模型的一個限制是,你只能使用一開始就位于該頁面上的對象。如果你開始動態地把對象添加到該頁面,那么你無法使用聲明性模型來把漂浮行為添加到其上。不過,借助于強制性模型,你能夠實現。
基于前面的例子,你要用一個據要求創建漂浮div的函數來代替pageLoad()函數。下列JavaScript函數會創建一個嵌有另一個div標簽(用作一個handlebar)的div標簽,然后把該div標簽插入到當前的頁面,并且最后把漂浮行為添加到div標簽:
然后,你只需要把一個按鈕添加到該調用createDraggableDiv()函數的頁面。現在,新的HTML體看上去具有如下形式:
這將允許你把很多的可拖放元素添加到你的頁面上,這說明了,一旦你理解了在以聲明方式使用Atlas和以編程方式使用它之間的關系,那么Atlas將表現出強大的威力和靈活性。作為參考,下面是動態拖放示例的完整實現代碼:
五. 聲明性Dropzone
我們可以在一個頁面上拖動HTML元素,然后讓它們位于其投放位置。然而,為了使該行為真正有用,當投放發生時,應該拋出一個事件。而且,所拋出的事件應該依賴于在何處發生投放。換句話說,需要把行為添加到一個給定HTML元素-由它來把這一行為轉換成一個"dropzone"或"投放目標",可以使用相同的方法把漂浮行為添加到一個HTML div標簽以便把它轉換成一個可拖放的元素。
在下列例子中,我將向你展示Atlas是如何支持dropzone概念的。在它的當前狀態中,Atlas并不支持與其支持漂浮元素一樣的方式來提供一種現成的行為以支持創建dropzone元素。然而,它確實實現了一個DragDropList元素和一個DraggableListItem元素的行為(這兩個元素聯用,允許你創建能夠通過拖放重新排序的列表)。如果你想進一步探討這一功能,你可以在網上找到若干使用DragDropList行為的好例子,例如,《Introduction to Drag And Drop with Atlas》。
dragdropzone行為的主要不利條件是,它僅與具有DragDropList行為的項一起工作。為了確定我上面描述的開放端點的dropzone功能的類型(它將與預定義的漂浮行為一同使用),你需要用JavaScript編寫你自己的dropzone行為類。幸好,這并不困難。
Atlas把若干OOP擴展添加到JavaScript中以使加強其擴展能力,例如命名空間,抽象類和接口。在編寫你自己的dropzone行為時你還要利用這些工具。如果你分析一下AtlasUIDragDrop.js文件的源碼(可以使用Visual Studio調試器),那么你會發現在那里定義了若干接口,這包括一個相應于Sys.UI.DragSource而另一個相應于Sys.UI.DropTarget。事實上,FloatingBehavior類和DraggableListItem類都實現了Sys.UI.DragSource接口,而Sys.UI.DropTarget被DragDropList類所實現。這兩個接口的代碼如下所示:
為什么你需要實現這些接口而不是簡單地編寫一些新類來支持拖放和dropzone呢?秘密是,在后臺,還有一個類DragDropManager,負責實際協調可拖放元素與dropzone元素之間的交互,并且它僅僅知道如何與實現IDragSource或IDropTarget接口的類一起工作。這個DragDropManager類注冊對于每一個可拖放的元素來說哪些dropzone是合法的目標,并處理MouseOver事件以決定何時一個dropzone上面具有一個可拖放的元素,以及其它你不需要自己做的大量事情。事實上,它處理得如此完美,以至后面你要編寫的dropzone行為需要極少的代碼。首先,創建一新的JavaScript文件DropZoneBehavior.js。我把我的JavaScript文件放到了一個子目錄scriptLibrary下,但是,這對于實現dropzone行為是不必要的。然后,把下列代碼復制到你的文件中:
我需要解釋一下這個類。首先要注意從第二(以"Custom.UI.DropZoneBehavior.registerClass"開始)到最后一行代碼。這是上面定義的dropZoneBehaviorClass注冊到Atlas的位置。registerClass方法的第一個參數相應于類的名字,第二個參數則相應于基類的名字。第三個參數相應于實現新類的接口。接下來的一行代碼使你的類可用于聲明性標記腳本。現在,我們回到開始,"Type.registerNamespace"方法允許你注冊你的定制命名空間。下一行使用一個匿名方法語法聲明我們的新類。這里使用了JavaScript面向對象的設計思想,這對于設計Atlas行為來說是必要的。在該匿名方法中,類方法Initialize,Dispose和getDescriptor都是一些簡單的標準方法,用于所有的行為類,而且在這個簡單實現中,你僅需要調用基方法(也就是,從這個例子的第二到最后一行代碼中所指定的基類的方法)即可。你要做的唯一特別的一點是,使用在Initialize方法中的Sys.UI.DragDropManager來注冊拖放目標。這里是大部分的拖放"魔術"所在。
然后,你實現IDropTarget方法。在這個例子中,你僅實現了兩個方法:this.canDrop與this.drop。對于canDrop,你只是簡單地返回true。其實,更有趣的邏輯可以放到其中,譬如實現有哪些div標簽被實際拖放到一個給定的目標上,或者決定相應于不同類型的漂浮div,在拖放它們時各自的不同行為;但是,在此情況下,你僅想簡單地實現IDropTarget-它允許任何漂浮div拖動到其上。你的"drop"方法的實現只是個框架而已。當一個漂浮元素被拖放到你的拖放目標之一時,將顯示一條警告消息指示已經發生了一些事情。現在,你已經有了一個拖放行為,它能夠與我們在上一個例子中所用的漂浮行為一同工作。
現在你應該創建一個頁面來展示你的新定制的dropzone行為。為此,你可以在前面示例的基礎上來實現。在Atlas腳本管理器中,除注冊AtlasUIDragDrop腳本以外,你還要注冊你的新的DropZoneBehavior腳本:
然后,你要把一個新的div標簽添加到HTML體,這可以被用作一個拖放的目標:
最后,你需要添加一個聲明性標記元素以添加你的定制DropZone行為到你計劃用作一個dropzone元素的div。該XML標記應該有如下所示形式:
剛才的代碼把一個dropzone添加到最初聲明的拖放示例中。當你在dropzone上拖動元素時,將出現一個警告消息框。你可以擴展這些代碼以便使你的定制dropzone行為的drop方法實現一些更為有趣的事情,例如激活當前的頁面中的其它JavaScript事件,甚至使用Atlas調用一個web服務-由它來為你處理服務器端代碼。 六. 強制性Dropzone
為了使用JavaScript代替聲明性腳本創建dropzone,僅需要使用定制的dropzone行為添加如下的JavaScript函數來初始化你的dropzone元素:
為了"鉤住"一切,你可以調用這個來自Atlas pageLoad()方法的addDropZoneBehavior函數(就象你在前面的示例中操作addFloatingBehavior函數一樣)。這樣可以把正確的行為依附到它們各自的HTML元素并且復制上面你使用聲明性標記所創建的拖放和dropzone功能。如果你想使此能夠動態工作,那么你只要添加你為上一個示例編寫的createDraggableDiv()函數即可。作為一種參考,下面是創建可編程dropzone的完整代碼:
除了dropzone行為以外,你可能還想寫你自己的漂浮行為。例如,默認地,帶有漂浮行為的元素只是簡單地停留在你放下它們的位置。然而,你可能想擴展這一特征以便你的漂浮div會"退回"到它原來的位置-當你把它放到一個投放區外的時候。另外,當你拖動它時,你可能想改變被拖放的元素看上去的樣子,或使它透明,或改變它的顏色,或全部替換原來的拖動圖像。所有這些都可以通過創建實現IDragSource接口的一種行為來實現,這與你創建一個實現IDropTarget接口的定制類是思路一樣。
七. 總結
本文應該為你擴展Atlas提供的基本拖放功能來創建你自己的行為和功能提供了一個起點。而且,你可以基于此創建控件;還可以在此基礎上繼續創建使用聲明性標記實現你的行為的Atlas擴展控件,或創建使用Atlas行為自動創建HTML元素的服務器端控件。這樣以來,你就可以進一步創建高級服務器端控件-或者是靜態的聲明性的,或者是強制性的,卻更復雜些但也更靈活。當然,這是一個超出本文題目的問題。不過,我希望,此后有人會嘗試服務器端Atlas編程,正象本文所作的客戶端Atlas腳本編程嘗試一樣。
運行結果
一. 簡介
本文旨在幫助讀者理解微軟的Atlas技術的某些方面的工作原理。Atlas的實現宗旨是簡化AJAX風格的Web程序開發。然而,就象所有其它技術一樣,為了更好地使用這個工具,你需要深入理解Atlas抽象的內在技術。Atlas抽象的一個關鍵之處是新的XML標記語法,目的是實現利用Atlas進行編程更為容易。借助于XML標記,開發者能夠以聲明性方式修改他們的代碼。然而,有時當一個開發者可能想以編程方式來改變其代碼時,他需要理解,在標記抽象層下面,他實際在與一些JavaScript及一些微軟開發的定制JavaScript庫打交道。為了展示Atlas聲明性模型與可編程模型之間的關系,我們將討論幾個例子,在這些示例中,我們將使用兩種模型來實現相同的功能。我將向你展示如何使用AtlasUIDragDrop庫文件來執行基本的拖放操作以及建立放置區。
[背景]
當我寫作本文時,Atlas仍處于其beta測試階段,并且在繼續修改中。本文中的這些示例適用于Atlas的四月CTP版本;因此,Atlas的更新的發行版本可能會影響本文的精確性。另外,還要注意,Atlas僅能與.NET 2.0一起工作。
二. 聲明性拖放
為了把拖放行為添加到一個div標簽,第一項任務是使用Atlas標記。通過拖放,我僅想實現能夠拖放一個對象并且讓它位于你想把它放置的地方。當把一個對象放置到一個指定的點時,在實際開發中所表現出的動作將在后面討論。為了配置你的網頁以便使用Atlas,你需要從微軟站點把Microsoft.Web.Atlas.dll文件下載到你的bin文件夾下并且使用下列入口配置你的web.config文件:
| <system.web> <pages> <controls> <add namespace="Microsoft.Web.UI" assembly="Microsoft.Web.Atlas" tagPrefix="atlas"/> <add namespace="Microsoft.Web.UI.Controls" assembly="Microsoft.Web.Atlas" tagPrefix="atlas"/> </controls> </pages> </system.web> |
接下來,你需要把一個Atlas腳本管理器控件添加到你的.aspx頁面并且使用AtlasUIDragDrop庫來配置:
| <atlas:ScriptManager ID="ScriptManager1" runat="server"> <Scripts> <atlas:ScriptReference ScriptName="AtlasUIDragDrop" /> </Scripts> </atlas:ScriptManager> |
然后,添加你想使之可拖放的div對象,并且確保它有一個拖放句柄:
| <div style="background-color:Red;height:800px;width:600px;"> <div id="draggableDiv" style="height:100px;width:100px;background-color:Blue;"> <div id="handleBar" style="height:20px;width:auto;background-color:Green;"> </div> </div> </div> |
最后,添加能夠使你的div成為可拖放的標記腳本:
| <script type="text/xml-script"> <page xmlns:script="http://schemas.microsoft.com/xml-script/2005"> <components> <control id="draggableDiv"> <behaviors> <floatingBehavior handle="handleBar"/> </behaviors> </control> </components> </page> </script> |
至此,你應該有了一個可拖放的div標簽。該示例展示了結合Atlas使用聲明性方式的簡單性和容易性。在Atlas所引入的術語中,你僅使用了聲明性標記來把漂浮行為添加到一個HTML元素。 三. 強制性拖放
為了使用編程方式來實現相同的功能,我們需要進行一些編程,但是不需要較多的編碼。你必須明白,當你把一個Atlas腳本管理器組件添加到你的頁面上時,你實際上是在下命令把Atlas JavaScript庫加載到你的頁面。這個Atlas庫提供了擴展DOM的客戶端類,并且提供允許你在一個瀏覽器中進行編碼的工具(盡管現在在Safari兼容性方面還存在一些問題)。這些客戶端類還允許你把你的HTML元素添加到行為。
為了切換到一個強制性模型,你需要用兩個JavaScript函數來代替XML標記。第一個函數是一個普通腳本用于把漂浮行為添加到一個HTML元素上。它利用了Atlas客戶端類來完成此功能:
| <script type="text/javascript"> function addFloatingBehavior(ctrl, ctrlHandle){ //創建新的漂浮行為對象 var floatingBehavior = new Sys.UI.FloatingBehavior(); //漂浮行為類具有一個Handle屬性 floatingBehavior.set_handle(ctrlHandle); //把對象參考值的為Atlas客戶端控件 var dragItem = new Sys.UI.Control(ctrl); //從Atlas控件中取得行為集合 //添加我們自己的漂浮行為 dragItem.get_behaviors().add(floatingBehavior); //運行該漂浮行為的內部javascript floatingBehavior.initialize(); } </script> |
這個函數使用兩個參數值:你想要拖放的HTML元素和實現該拖放行為的拖放句柄HTML元素。然后,你實例化一個新的Atlas客戶端行為對象。該漂浮行為具有一個handle屬性-你把HTML元素的句柄傳遞給它。然后,你需要基于你想使之成為可拖放的控件以創建一個新的客戶端控件對象。把你的div標簽轉換成一個Atlas客戶端控件能夠使你把Atlas行為添加到它上面。你可以使用get_behaviors()方法來返回一個行為集合,并且使用add方法來把一個新行為添加到你的HTML對象。最后,你調用行為對象的initialize()方法以允許在內部配置行為自身。我們將在本文剩下的部分中一直使用這個工具函數。
現在,當頁面裝載時,你需要調用addFloatingBehavior函數。說實話,這是編寫這個示例中最有難度的編碼部分。腳本管理器并不是簡單地創建一個到Atlas JavaScript庫的引用,我推想它實際把該庫腳本裝載到DOM。在任何情況下,這意味著,只有頁面中的其它一切都裝載后該庫才得到加載。這樣以來,我們所面臨的問題在于,裝載該庫后,沒有標準的方法來使我們的添加漂浮行為的代碼運行;并且如果我們在加載該庫前運行它,那么我們可以簡單地生成JavaScript錯誤-因為我們調用的所有的Atlas方法都不能被發現。
其實,存在好幾種方法可以來解決這個問題,但是最容易的方法是使用一個定制的Atlas事件pageLoad()-這個事件實際只在裝載這些庫后才調用它。為了把漂浮行為添加到你的div標簽中,當第一次加載頁面時(但是在庫腳本裝載后),你僅需要編寫如下代碼:
| <script type="text/javascript"> function pageLoad(){ addFloatingBehavior(document.getElementById('draggableDiv'),document.getElementById('handleBar')); } </script> |
這可以使用一種Atlas腳本速記方式來書寫-用"$()"代替"document.getElementById()":
| <script type="text/javascript"> function pageLoad(){ addFloatingBehavior($('draggableDiv'),$('handleBar')); } </script> |
在此,可以看到,你有一個可拖動的div,其行為與你使用聲明性模型編寫的可拖動的div完全一致。
四. 動態拖放
既然聲明性模型比強制性模型更為清晰,那么為什么你還要編寫自己的JavaScript來處理Atlas行為呢?其實,這種聲明性模型的一個限制是,你只能使用一開始就位于該頁面上的對象。如果你開始動態地把對象添加到該頁面,那么你無法使用聲明性模型來把漂浮行為添加到其上。不過,借助于強制性模型,你能夠實現。
基于前面的例子,你要用一個據要求創建漂浮div的函數來代替pageLoad()函數。下列JavaScript函數會創建一個嵌有另一個div標簽(用作一個handlebar)的div標簽,然后把該div標簽插入到當前的頁面,并且最后把漂浮行為添加到div標簽:
| function createDraggableDiv() { var panel= document.createElement("div"); panel.style.height="100px"; panel.style.width="100px"; panel.style.backgroundColor="Blue"; var panelHandle = document.createElement("div"); panelHandle.style.height="20px"; panelHandle.style.width="auto"; panelHandle.style.backgroundColor="Green"; panel.appendChild(panelHandle); var target = $('containerDiv').appendChild(panel); addFloatingBehavior(panel, panelHandle); } |
然后,你只需要把一個按鈕添加到該調用createDraggableDiv()函數的頁面。現在,新的HTML體看上去具有如下形式:
| <input type="button" value="Add Floating Div" /> <div id="containerDiv" style="background-color:Purple;height:800px;width:600px;"/> |
這將允許你把很多的可拖放元素添加到你的頁面上,這說明了,一旦你理解了在以聲明方式使用Atlas和以編程方式使用它之間的關系,那么Atlas將表現出強大的威力和靈活性。作為參考,下面是動態拖放示例的完整實現代碼:
| <%@ Page Language="C#" %> <!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>Imperative Drag and Drop II</title> <script type="text/javascript"> function createDraggableDiv() { var panel= document.createElement("div"); panel.style.height="100px"; panel.style.width="100px"; panel.style.backgroundColor="Blue"; var panelHandle = document.createElement("div"); panelHandle.style.height="20px"; panelHandle.style.width="auto"; panelHandle.style.backgroundColor="Green"; panel.appendChild(panelHandle); var target = $('containerDiv').appendChild(panel); addFloatingBehavior(panel, panelHandle); } function addFloatingBehavior(ctrl, ctrlHandle){ var floatingBehavior = new Sys.UI.FloatingBehavior(); floatingBehavior.set_handle(ctrlHandle); var dragItem = new Sys.UI.Control(ctrl); dragItem.get_behaviors().add(floatingBehavior); floatingBehavior.initialize(); } </script> </head> <body> <form id="form1" runat="server"> <atlas:ScriptManager ID="ScriptManager1" runat="server"> <Scripts> <atlas:ScriptReference ScriptName="AtlasUIDragDrop" /> </Scripts> </atlas:ScriptManager> <h2>Imperative Drag and Drop Code with javascript: demonstrate dynamic loading of behaviors</h2> <input type="button" value="Add Floating Div" /> <div id="containerDiv" style="background-color:Purple;height:800px;width:600px;"/> </form> </body> </html> |
我們可以在一個頁面上拖動HTML元素,然后讓它們位于其投放位置。然而,為了使該行為真正有用,當投放發生時,應該拋出一個事件。而且,所拋出的事件應該依賴于在何處發生投放。換句話說,需要把行為添加到一個給定HTML元素-由它來把這一行為轉換成一個"dropzone"或"投放目標",可以使用相同的方法把漂浮行為添加到一個HTML div標簽以便把它轉換成一個可拖放的元素。
在下列例子中,我將向你展示Atlas是如何支持dropzone概念的。在它的當前狀態中,Atlas并不支持與其支持漂浮元素一樣的方式來提供一種現成的行為以支持創建dropzone元素。然而,它確實實現了一個DragDropList元素和一個DraggableListItem元素的行為(這兩個元素聯用,允許你創建能夠通過拖放重新排序的列表)。如果你想進一步探討這一功能,你可以在網上找到若干使用DragDropList行為的好例子,例如,《Introduction to Drag And Drop with Atlas》。
dragdropzone行為的主要不利條件是,它僅與具有DragDropList行為的項一起工作。為了確定我上面描述的開放端點的dropzone功能的類型(它將與預定義的漂浮行為一同使用),你需要用JavaScript編寫你自己的dropzone行為類。幸好,這并不困難。
Atlas把若干OOP擴展添加到JavaScript中以使加強其擴展能力,例如命名空間,抽象類和接口。在編寫你自己的dropzone行為時你還要利用這些工具。如果你分析一下AtlasUIDragDrop.js文件的源碼(可以使用Visual Studio調試器),那么你會發現在那里定義了若干接口,這包括一個相應于Sys.UI.DragSource而另一個相應于Sys.UI.DropTarget。事實上,FloatingBehavior類和DraggableListItem類都實現了Sys.UI.DragSource接口,而Sys.UI.DropTarget被DragDropList類所實現。這兩個接口的代碼如下所示:
| Sys.UI.IDragSource = function() { this.get_dataType = Function.abstractMethod; this.get_data = Function.abstractMethod; this.get_dragMode = Function.abstractMethod; this.onDragStart = Function.abstractMethod; this.onDrag = Function.abstractMethod; this.onDragEnd = Function.abstractMethod; } Sys.UI.IDragSource.registerInterface('Sys.UI.IDragSource'); Sys.UI.IDropTarget = function() { this.get_dropTargetElement = Function.abstractMethod; this.canDrop = Function.abstractMethod; this.drop = Function.abstractMethod; this.onDragEnterTarget = Function.abstractMethod; this.onDragLeaveTarget = Function.abstractMethod; this.onDragInTarget = Function.abstractMethod; } Sys.UI.IDropTarget.registerInterface('Sys.UI.IDropTarget'); |
為什么你需要實現這些接口而不是簡單地編寫一些新類來支持拖放和dropzone呢?秘密是,在后臺,還有一個類DragDropManager,負責實際協調可拖放元素與dropzone元素之間的交互,并且它僅僅知道如何與實現IDragSource或IDropTarget接口的類一起工作。這個DragDropManager類注冊對于每一個可拖放的元素來說哪些dropzone是合法的目標,并處理MouseOver事件以決定何時一個dropzone上面具有一個可拖放的元素,以及其它你不需要自己做的大量事情。事實上,它處理得如此完美,以至后面你要編寫的dropzone行為需要極少的代碼。首先,創建一新的JavaScript文件DropZoneBehavior.js。我把我的JavaScript文件放到了一個子目錄scriptLibrary下,但是,這對于實現dropzone行為是不必要的。然后,把下列代碼復制到你的文件中:
| Type.registerNamespace('Custom.UI'); Custom.UI.DropZoneBehavior = function() { Custom.UI.DropZoneBehavior.initializeBase(this); this.initialize = function() { Custom.UI.DropZoneBehavior.callBaseMethod(this, 'initialize'); //把我們自己注冊為一個拖放目標. Sys.UI.DragDropManager.registerDropTarget(this); } this.dispose = function() { Custom.UI.DropZoneBehavior.callBaseMethod(this, 'dispose'); } this.getDescriptor = function() { var td = Custom.UI.DropZoneBehavior.callBaseMethod(this, 'getDescriptor'); return td; } //IDropTarget成員. this.get_dropTargetElement = function() { return this.control.element; } this.drop = function(dragMode, type, data) { alert('dropped'); } this.canDrop = function(dragMode, dataType) { return true; } this.onDragEnterTarget = function(dragMode, type, data) {} this.onDragLeaveTarget = function(dragMode, type, data) {} this.onDragInTarget = function(dragMode, type, data) {} } Custom.UI.DropZoneBehavior.registerClass('Custom.UI.DropZoneBehavior', Sys.UI.Behavior, Sys.UI.IDragSource, Sys.UI.IDropTarget, Sys.IDisposable); Sys.TypeDescriptor.addType('script', 'DropZoneBehavior', Custom.UI.DropZoneBehavior); |
我需要解釋一下這個類。首先要注意從第二(以"Custom.UI.DropZoneBehavior.registerClass"開始)到最后一行代碼。這是上面定義的dropZoneBehaviorClass注冊到Atlas的位置。registerClass方法的第一個參數相應于類的名字,第二個參數則相應于基類的名字。第三個參數相應于實現新類的接口。接下來的一行代碼使你的類可用于聲明性標記腳本。現在,我們回到開始,"Type.registerNamespace"方法允許你注冊你的定制命名空間。下一行使用一個匿名方法語法聲明我們的新類。這里使用了JavaScript面向對象的設計思想,這對于設計Atlas行為來說是必要的。在該匿名方法中,類方法Initialize,Dispose和getDescriptor都是一些簡單的標準方法,用于所有的行為類,而且在這個簡單實現中,你僅需要調用基方法(也就是,從這個例子的第二到最后一行代碼中所指定的基類的方法)即可。你要做的唯一特別的一點是,使用在Initialize方法中的Sys.UI.DragDropManager來注冊拖放目標。這里是大部分的拖放"魔術"所在。
然后,你實現IDropTarget方法。在這個例子中,你僅實現了兩個方法:this.canDrop與this.drop。對于canDrop,你只是簡單地返回true。其實,更有趣的邏輯可以放到其中,譬如實現有哪些div標簽被實際拖放到一個給定的目標上,或者決定相應于不同類型的漂浮div,在拖放它們時各自的不同行為;但是,在此情況下,你僅想簡單地實現IDropTarget-它允許任何漂浮div拖動到其上。你的"drop"方法的實現只是個框架而已。當一個漂浮元素被拖放到你的拖放目標之一時,將顯示一條警告消息指示已經發生了一些事情。現在,你已經有了一個拖放行為,它能夠與我們在上一個例子中所用的漂浮行為一同工作。
現在你應該創建一個頁面來展示你的新定制的dropzone行為。為此,你可以在前面示例的基礎上來實現。在Atlas腳本管理器中,除注冊AtlasUIDragDrop腳本以外,你還要注冊你的新的DropZoneBehavior腳本:
| <atlas:ScriptManager ID="ScriptManager1" runat="server"> <Scripts> <atlas:ScriptReference ScriptName="AtlasUIDragDrop" /> <atlas:ScriptReference Path="scriptLibrary/DropZoneBehavior.js" /> </Scripts> </atlas:ScriptManager> |
然后,你要把一個新的div標簽添加到HTML體,這可以被用作一個拖放的目標:
| <div style="background-color:Red;height:200px;width:200px;"> <div id="draggableDiv" style="height:100px;width:100px;background-color:Blue;"> <div id="handleBar" style="height:20px;width:auto;background-color:Green;"> </div> </div> </div> <div id="dropZone" style="background-color:cornflowerblue;height:200px;width:200px;"> Drop Zone </div> |
最后,你需要添加一個聲明性標記元素以添加你的定制DropZone行為到你計劃用作一個dropzone元素的div。該XML標記應該有如下所示形式:
| <script type="text/xml-script"> <page xmlns:script="http://schemas.microsoft.com/xml-script/2005"> <components> <control id="dropZone"> <behaviors> <DropZoneBehavior/> </behaviors> </control> <control id="draggableDiv"> <behaviors> <floatingBehavior handle="handleBar"/> </behaviors> </control> </components> </page> </script> |
剛才的代碼把一個dropzone添加到最初聲明的拖放示例中。當你在dropzone上拖動元素時,將出現一個警告消息框。你可以擴展這些代碼以便使你的定制dropzone行為的drop方法實現一些更為有趣的事情,例如激活當前的頁面中的其它JavaScript事件,甚至使用Atlas調用一個web服務-由它來為你處理服務器端代碼。 六. 強制性Dropzone
為了使用JavaScript代替聲明性腳本創建dropzone,僅需要使用定制的dropzone行為添加如下的JavaScript函數來初始化你的dropzone元素:
| function addDropZoneBehavior(ctrl){ var dropZone = new Sys.UI.Control(ctrl); var dropZoneBehavior = new Custom.UI.DropZoneBehavior(); dropZone.get_behaviors().add(dropZoneBehavior); dropZoneBehavior.initialize(); } |
為了"鉤住"一切,你可以調用這個來自Atlas pageLoad()方法的addDropZoneBehavior函數(就象你在前面的示例中操作addFloatingBehavior函數一樣)。這樣可以把正確的行為依附到它們各自的HTML元素并且復制上面你使用聲明性標記所創建的拖放和dropzone功能。如果你想使此能夠動態工作,那么你只要添加你為上一個示例編寫的createDraggableDiv()函數即可。作為一種參考,下面是創建可編程dropzone的完整代碼:
| <%@ Page Language="C#" %> <!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 id="Head1" runat="server"> <title>Imperative Drop Targets</title> <script type="text/javascript"> function addFloatingBehavior(ctrl, ctrlHandle){ var floatingBehavior = new Sys.UI.FloatingBehavior(); floatingBehavior.set_handle(ctrlHandle); var dragItem = new Sys.UI.Control(ctrl); dragItem.get_behaviors().add(floatingBehavior); floatingBehavior.initialize(); } function addDropZoneBehavior(ctrl){ var dropZone = new Sys.UI.Control(ctrl); var dropZoneBehavior = new Custom.UI.DropZoneBehavior(); dropZone.get_behaviors().add(dropZoneBehavior); dropZoneBehavior.initialize(); } function pageLoad(){ addDropZoneBehavior($('dropZone')); addFloatingBehavior($('draggableDiv'),$('handleBar')); } </script> </head> <body> <form id="form1" runat="server"> <atlas:ScriptManager ID="ScriptManager1" runat="server"> <Scripts> <atlas:ScriptReference ScriptName="AtlasUIDragDrop" /> <atlas:ScriptReference Path="scriptLibrary/DropZoneBehavior.js" /> </Scripts> </atlas:ScriptManager> <h2>Imperative Drop Targets with javacript</h2> <div style="background-color:Red;height:200px;width:200px;"> <div id="draggableDiv" style="height:100px;width:100px;background-color:Blue;"> <div id="handleBar" style="height:20px;width:auto;background-color:Green;"> </div> </div> </div> <div id="dropZone" style="background-color:cornflowerblue; height:200px;width:200px;">Drop Zone</div> </form> </body> </html> |
除了dropzone行為以外,你可能還想寫你自己的漂浮行為。例如,默認地,帶有漂浮行為的元素只是簡單地停留在你放下它們的位置。然而,你可能想擴展這一特征以便你的漂浮div會"退回"到它原來的位置-當你把它放到一個投放區外的時候。另外,當你拖動它時,你可能想改變被拖放的元素看上去的樣子,或使它透明,或改變它的顏色,或全部替換原來的拖動圖像。所有這些都可以通過創建實現IDragSource接口的一種行為來實現,這與你創建一個實現IDropTarget接口的定制類是思路一樣。
七. 總結
本文應該為你擴展Atlas提供的基本拖放功能來創建你自己的行為和功能提供了一個起點。而且,你可以基于此創建控件;還可以在此基礎上繼續創建使用聲明性標記實現你的行為的Atlas擴展控件,或創建使用Atlas行為自動創建HTML元素的服務器端控件。這樣以來,你就可以進一步創建高級服務器端控件-或者是靜態的聲明性的,或者是強制性的,卻更復雜些但也更靈活。當然,這是一個超出本文題目的問題。不過,我希望,此后有人會嘗試服務器端Atlas編程,正象本文所作的客戶端Atlas腳本編程嘗試一樣。
總結
以上是生活随笔為你收集整理的ASP.NET 2.0+Atlas编写鼠标拖放程序(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP 解析xml(包含非英文字符)
- 下一篇: 在Eclipse 2.0中使用版本控制系