在Ajax程式中實現傳統傳統型程式中異常簡單的拖放功能卻並不是件容易的事情。然而Web上的拖放功能又如此的讓人癡迷,所以幾乎每個成熟的Ajax類庫都提供了自己的一套實現拖放的封裝,ASP.NET AJAX (Atlas) 自然也不例外。本文將總結並簡要分析ASP.NET AJAX (Atlas) 中拖放功能的6種不同的實現方法,希望能夠協助朋友們選出最適合實際需求的方法。
其中第1到第4種方案,在我的《ASP.NET Ajax程式設計——第I卷:伺服器端ASP.NET 2.0 AJAX Extensions與ASP.NET AJAX Control Toolkit》一書中有詳細介紹(4月出版),本文中的代碼和圖示也節選自該書。第5第6種方案,在我的《ASP.NET 2.0 Ajax程式設計——第II卷:用戶端Microsoft AJAX Library》一書中將有詳細介紹(暫訂7月出版)。
不過縱觀這些解決方案,我很遺憾的發現,要麼是使用簡單,可定製能力差,要麼就是可定製能力強,但使用起來要寫很多代碼。希望ASP.NET AJAX (Atlas) 團隊能夠再接再厲,努力把這個重要功能做得更好。或者我有哪種方法漏掉了,也請朋友們幫忙補充一下。
[1] 使用伺服器端DragOverlayExtender或用戶端DragOverlayBehavior
伺服器端的DragOverlayExtender就是靠著用戶端DragOverlayBehavior而實現的,前者是後者在伺服器端的組件化封裝,所以我們將二者放在一起討論。
這個“拖放”功能很簡單,其實這隻是個“拖拽”,而沒有“投放”。也就是說,你可以隨意將某個Panel在頁面中拖來拖去,不過卻沒有什麼固定的地方可以“投放”,就像在Windows案頭上拖放某個視窗的位置一樣——其實用處不大,也沒有提供什麼可定製能力。但它使用起來非常簡單,也支援將Panel的位置儲存在Profile中。
下面是一段DragOverlayExtender的範例程式碼,至於DragOverlayBehavior的用法,請查看DragOverlayExtender頁面產生的HTML代碼:
<asp:Login ID="floatLogin" BackColor="white"
BorderStyle="Solid" BorderColor="black"
runat="server">
</asp:Login>
<asp:DragOverlayExtender ID="DragOverlayExtender2"
Enabled="true" TargetControlID="floatLogin"
runat="server" />
效果如下:
[2] 使用伺服器端DragPanel
DragPanel是ASP.NET AJAX Control Toolkit中的一個擴充器控制項。其功能基本與DragOverlayExtender和DragOverlayBehavior一樣,且同樣可以儲存Panel的位置資訊至Profile中。不同之處在於,DragOverlayExtender和DragOverlayBehavior的拖拽實現方式中,滑鼠放在整個Panel的任何部分都可以開始拖拽,而DragPanel在進行拖拽時,只有滑鼠放在指定的DragHandle(類似於Windows視窗的標題列部分)中才能開始拖拽。
對於DragHandle的擴充性和實用性,同樣不敢恭維。
下面是一段範例程式碼:
<asp:Panel ID="floatPanel" CssClass="floatPanel" runat="server">
<asp:Panel ID="floatPanelHandle" CssClass="handle" runat="server">
視窗的拖動
</asp:Panel>
<div class="content">
在Windows中,對視窗的拖動似乎成了我們習以為常的事情。
………………
………………
Window視窗的表現行為一樣。
</div>
</asp:Panel>
<ajaxToolkit:DragPanelExtender ID="dpe" TargetControlID="floatPanel"
DragHandleID="floatPanelHandle" runat="server">
</ajaxToolkit:DragPanelExtender>
效果如下:
[3] 使用伺服器端ReorderList
ASP.NET AJAX Control Toolkit中的ReorderList控制項將在頁面中呈現出一個由資料繫結自動產生的條目列表。使用者可以通過滑鼠拖動某一項來直接改變該列表中條目彼此之間的相對位置關係,且在拖動的過程中,ReorderList控制項提供了豐富的、可定製的視覺效果。當使用者在某個位置放開滑鼠之後,ReorderList控制項也將同樣會自動通知與其繫結資料原始檔控制,以Ajax的非同步或整頁回送的同步方式補救伺服器端資料。
ReorderList控制項的使用比較簡單(伺服器端控制項),功能也相當的豐富,擴充能力也不錯。不過仍稱不上最靈活,比如我們想把條目在多個ReorderList之間拖放,那麼就沒辦法實現了——因此,不要指望它能實現WebPart那樣的功能。
詳細介紹請參考:《使用ASP.NET AJAX Control Toolkit中的ReorderList控制項實現用滑鼠拖動改變條目順序》
下面是一段範例程式碼:
<ajaxToolkit:ReorderList ID="musicList" CssClass="musicList"
DragHandleAlignment="Left" PostBackOnReorder="false"
DataSourceID="musicDataSource" DataKeyField="Id"
SortOrderField="Order" runat="server">
<ItemTemplate>
<ajaxToolkit:Rating ID="rating" runat="server"
CssClass="rating" StarCssClass="ratingStar"
FilledStarCssClass="filledRatingStar" EmptyStarCssClass="emptyRatingStar"
CurrentRating='<%# Bind("Rating") %>' MaxRating="5"
ReadOnly="true">
</ajaxToolkit:Rating>
</ItemTemplate>
<ReorderTemplate>
<div class="dragDue">
Drop Here!
</div>
</ReorderTemplate>
<DragHandleTemplate>
<asp:Label ID="lbTitle" CssClass="dragHandle"
ToolTip="Drag Me!" runat="server" Text='<%# Bind("Name") %>'>
</asp:Label>
</DragHandleTemplate>
</ajaxToolkit:ReorderList>
效果挺酷的:
[4] 使用UpdatePanel與ASP.NET AJAX中的新版本WebPart控制項
ASP.NET 2.0中的WebPart相關的控制項雖然非常豐富,便於使用且功能強大,我們在程式中也很需要它所提供的拖拽功能,但它卻存在著兩個致命的缺陷:
- 拖放功能只支援IE瀏覽器。
- 每次使用者通過拖放改變更配置件的位置之後,頁面總會自動進行回送以儲存當前的設定。
其中第一個問題可以通過ASP.NET AJAX中的新版本WebPart控制項搞定,第二個問題可以通過添加UpdatePanel搞定,本來在CTP版本中的ASP.NET AJAX裡面,這些功能均已經完美實現了。誰知道在最新的Futures CTP中,卻又不好用了。
既然現在已經不能用了,也就沒必要分析其優點缺點了。不過還是給出一張吧,緬懷一下曾經的輝煌(注意,這可是在Firefox中啊!)……
[5] 使用用戶端DragDropList
DragDropList定義於ASP.NET AJAX Futures CTP中,功能非常強大,且全部在用戶端實現,給伺服器端減輕了不少的壓力。使用DragDropList實現第4種解決方案中的WebPart類似的效果完全沒有問題,不過唯一讓人感到遺憾的就是,其擴充功能不是很好,使用者雖然可以隨便將某個Panel從一個地區拖到另一個地區,但拖拽的結果卻很難持久化下來……且使用起來也不是那麼的容易,效率上更是不敢恭維……總之,這是個很讓人矛盾的東西,有些雞肋的感覺。
我曾經在《使用ASP.NET Atlas實現拖放(Drag & Drop)效果(下)》這篇文章中給出過DragDropList的樣本程式,雖然是基於CTP版本的ASP.NET AJAX ,不過實際上並不需要多少修改就能運行於最新版本之上。感興趣的朋友可以看看,也可以到官方論壇上搜尋一下相關的主題。
[6] 在用戶端自行實現IDragSource和IDropTarget介面
來到了這個解決方案,可以說你對ASP.NET AJAX中的拖拽實現有了一個較深入的瞭解。上面的DragDropList其實就是實現了IDragSource和IDropTarget介面,其中前者用來定義可以被拖拽的項目,後者用來定義可以被投放的地區。詳細理論上的說明,可以參考我的文章《使用ASP.NET Atlas實現拖放(Drag & Drop)效果(上)》,雖然目前已經有所變化,不過仍可以參考。
這種實現方案應該說是最為強大的了,想要什麼功能,肯定都能實現。不過實際開發中的難度也不小——甚至可以說是相當複雜,Jeff Prosise的這篇文章《Implementing Drag-Drop in ASP.NET AJAX》給出了一個非常簡單的樣本程式,感興趣想要學習的朋友不妨看看……