随笔-312  评论-12034  文章-2  trackbacks-256

在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相关的控件虽然非常丰富,易于使用且功能强大,我们在程序中也很需要它所提供的拖拽功能,但它却存在着两个致命的缺陷:

  1. 拖放功能只支持IE浏览器。
  2. 每次用户通过拖放改变配件的位置之后,页面总会自动进行回送以保存当前的设定。

其中第一个问题可以通过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》给出了一个非常简单的示例程序,感兴趣想要学习的朋友不妨看看……

posted on 2007-03-26 08:15 Dflying Chen 阅读(7360) 评论(50)  编辑 收藏 网摘 所属分类: ASP.NET AJAX (Atlas)

评论:
#1楼 2007-03-26 08:17 | jerry[未注册用户]
刚到公司就看见新文章 开心啊
  回复  引用    
#2楼 2007-03-26 08:21 | JesseZhao      
很期待你的新书啊
  回复  引用  查看    
#3楼 2007-03-26 08:31 | anikin      
我看到别人做了一个dragdrop extender,不过我没使用过
  回复  引用  查看    
#4楼[楼主] 2007-03-26 08:37 | Dflying Chen      
@jerry
@JesseZhao
谢谢支持

  回复  引用  查看    
#5楼[楼主] 2007-03-26 08:37 | Dflying Chen      
@anikin
dragdrop extender似乎不错啊

  回复  引用  查看    
#6楼 2007-03-26 08:49 | teana[未注册用户]
好文。。
  回复  引用    
#7楼[楼主] 2007-03-26 08:51 | Dflying Chen      
@teana
:)

  回复  引用  查看    
#8楼[楼主] 2007-03-26 08:51 | Dflying Chen      
@anikin
dragdrop extender在什么地方有介绍呢?我找了一下,没看到阿

  回复  引用  查看    
#9楼 2007-03-26 08:55 | 老刘.      
收藏来研究,呵呵。支持Dflying:)
  回复  引用  查看    
#10楼 2007-03-26 09:13 | 陈招展      
收藏!!
  回复  引用  查看    
#11楼 2007-03-26 09:29 | e表      
拖放做起来是有点麻烦. ( 水晶报表杀手 -- e表, 它避免了大量的复杂SQL编写以及编程来准备数据。轻松实现复杂的统计报表,详见: http://my5155.meibu.com">http://my5155.meibu.com )
  回复  引用  查看    
#12楼[楼主] 2007-03-26 09:29 | Dflying Chen      
@老刘.
@陈招展
谢谢支持!

  回复  引用  查看    
#13楼[楼主] 2007-03-26 09:29 | Dflying Chen      
@e表
……这是广告么?

  回复  引用  查看    
#14楼 2007-03-26 09:42 | anikin      
@Dflying Chen
http://www.codeproject.com/Ajax/MakingGoogleIG.asp">http://www.codeproject.com/Ajax/MakingGoogleIG.asp

这篇文章的作者自己写了个custom dragdrop extender

  回复  引用  查看    
#15楼 2007-03-26 09:54 | roydu[未注册用户]
感觉没有直接写javascript好~
  回复  引用    
#16楼 2007-03-26 09:56 | duhaha[未注册用户]
好文章
==
http://***让你好玩

  回复  引用    
#17楼[楼主] 2007-03-26 09:56 | Dflying Chen      
@anikin
cool,我去看看,学习一下

  回复  引用  查看    
#18楼[楼主] 2007-03-26 09:57 | Dflying Chen      
@roydu
第六种方法就是直接写JavaScript的

  回复  引用  查看    
#19楼[楼主] 2007-03-26 09:57 | Dflying Chen      
@duhaha
………………你的网站确实挺有创意的

  回复  引用  查看    
#20楼 2007-03-26 10:48 | Clark Zheng      
这个一定要研究一哈
  回复  引用  查看    
#21楼 2007-03-26 11:23 | firefox[未注册用户]
好好研究,总结的很细致.
  回复  引用    
#22楼[楼主] 2007-03-26 14:27 | Dflying Chen      
@Clark Zheng
@firefox
谢谢支持!

  回复  引用  查看    
#23楼 2007-03-26 15:00 | zrlhappy      
先收藏再研究!
  回复  引用  查看    
#24楼 2007-03-26 17:21 | 流云萧[未注册用户]
@Dflying Chen
你现在是我的偶像了..我要朝你看齐..我现在一天20个小时在学习.NET

  回复  引用    
#25楼[楼主] 2007-03-26 17:40 | Dflying Chen      
@zrlhappy
谢谢

  回复  引用  查看    
#26楼[楼主] 2007-03-26 17:41 | Dflying Chen      
@流云萧
过奖了:)

  回复  引用  查看    
#27楼 2007-03-26 18:16 | Cat Chen      
最好用的还是最后一种方法,代码的话——如果你觉得DragDropList的代码可信,可以继承自它。
  回复  引用  查看    
#28楼[楼主] 2007-03-26 19:07 | Dflying Chen      
@Cat Chen
记得以前DragDropList是sealed的,刚刚看了一下,好像可以继承了,嘿嘿,不错

  回复  引用  查看    
#29楼 2007-03-26 20:00 | 锦瑟[未注册用户]
MSN Space里管理各个板块的拖放,是基于什么实现的呢?
  回复  引用    
#30楼[楼主] 2007-03-26 20:03 | Dflying Chen      
@锦瑟
这是用它自定义的一系列架构

  回复  引用  查看    
#31楼 2007-03-26 20:27 | Jeffrey Zhao      
@Dflying Chen
现在的没有所谓的sealed class了。而且其实当时sealed也只是个标记,人为改一下就骗过类库了,呵呵。

  回复  引用  查看    
#32楼 2007-03-26 22:07 | search-article[未注册用户]
学习学习。。。
  回复  引用    
#33楼[楼主] 2007-03-27 13:48 | Dflying Chen      
@Jeffrey Zhao
哦?现在没有拉?为什么没有啊?

  回复  引用  查看    
#34楼[楼主] 2007-03-27 13:48 | Dflying Chen      
@search-article
:)

  回复  引用  查看    
#35楼 2007-03-27 18:08 | Ring      
好东东 !!
  回复  引用  查看    
#36楼[楼主] 2007-03-27 21:56 | Dflying Chen      
@Ring
:)

  回复  引用  查看    
#37楼 2007-03-28 05:42 | Jeffrey Zhao      
@Dflying Chen
因为没有用阿,为什么要有Sealed Class呢?我们不去继承它不就可以了,JS那么灵活拦也拦不住。而且现在又是prototype的面向对象实现方式了,也就是说,没有真正的“私有成员”了,现在的私有成员只是用下划线作为名字的开头用来标明而已。

  回复  引用  查看    
#38楼 2007-03-28 17:41 | leoxu      
[4] 使用UpdatePanel与ASP.NET AJAX中的新版本WebPart控件
这种拖动,我用过。 http://8jt.cn">http://8jt.cn 大家注册完去试试。
是用ATLAS写的。新版本不支持。哈哈。欢迎交流。

  回复  引用  查看    
#39楼[楼主] 2007-03-28 23:35 | Dflying Chen      
@leoxu
……

  回复  引用  查看    
#40楼[楼主] 2007-03-28 23:36 | Dflying Chen      
@Jeffrey Zhao
呵呵,留着一个看着也爽阿

  回复  引用  查看    
#41楼 2007-04-06 14:13 | smile633[未注册用户]
请问楼主一个问题。我最近在微软网站上下载了ASP.NET 2.0 AJAX Extensions安装程序,安装后运行里面的例子,IE报错说找不到Sys,是什么原因啊
  回复  引用    
#42楼[楼主] 2007-04-07 13:25 | Dflying Chen      
@smile633
主要有这四种原因:
1. 浏览器没法加载经过压缩后的脚本文件。
2. web.config中没有配置好ScriptResourceHandler。
3. IIS中没有将Web站点的虚拟目录作为“应用程序”运行。
4. 请求ScriptResource.axd时发生404异常。

详情请参考:http://weblogs.asp.net/chrisri/archive/2007/02/02/demystifying-sys-is-undefined.aspx">http://weblogs.asp.net/chrisri/archive/2007/02/02/demystifying-sys-is-undefined.aspx

  回复  引用  查看    
#43楼 2007-05-18 16:37 | 路人[未注册用户]
用webparts+update的方法, " 其中第一个问题可以通过ASP.NET AJAX中的新版本WebPart控件搞定,"

这是什么意思呢? ASP.NET AJAX 模板建的网站里, webparts就是新版本了吗??

  回复  引用    
#44楼[楼主] 2007-05-19 22:39 | Dflying Chen      
@路人
需要配置一下web.config
在Web.config文件的<system.web>节的<pages>小节中添加如下的<tagMapping>代码即可:
<tagMapping>
<add tagType="System.Web.UI.WebControls.WebParts.WebPartManager" mappedTagType="Microsoft.Web.Preview.UI.Controls.WebParts.WebPartManager"/>
<add tagType="System.Web.UI.WebControls.WebParts.WebPartZone" mappedTagType="Microsoft.Web.Preview.UI.Controls.WebParts.WebPartZone"/>
</tagMapping>

  回复  引用  查看    
#45楼 2007-05-21 15:21 | 小三[未注册用户]
怎么不能留言了?
  回复  引用    
#46楼 2007-05-21 15:23 | 小三[未注册用户]
请教您一个问题。我按照您新书上227页的方法。为DragPanelExtender配置了ProfilePropertyName,想在第2次开启的时候纪录上一次的位置。可是失败了。并没有报错。想请教您怎么解决?谢谢
  回复  引用    
#47楼[楼主] 2007-05-22 19:51 | Dflying Chen      
@小三
可以留言

  回复  引用  查看    
#48楼[楼主] 2007-05-22 19:52 | Dflying Chen      
@小三
用嗅探器看看传输的HTTP数据,然后贴出来好么?

  回复  引用  查看    
#49楼 2007-08-29 11:32 | Swhsu[未注册用户]
您好:
想要請問上面六種拖曳的方式,
哪一種可以做成多重選取物件來拖曳呢?
謝謝您的幫忙啊!

  回复  引用    



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 687809




相关文章:

相关链接: