Asp.net Ajax实现拖放实战

    摘要:关于Asp.net Ajax框架来实现拖放有多种方式,http://www.cncms.com.cn/ajax/10093_2.htm
比较简单的一种是用AjaxControlToolkit中的服务器控件如DragPanelExtender等
但是在效率和拖放之间数据的交换细节等方面与实际应用有些偏差。估完全采用客户实现IDragSource和IDropTarget接口。
可以先参考陈黎夫先生的http://www.cnblogs.com/dflying/archive/2007/05/29/763564.html


    项目背景:本功能是为了实现事业单位的绩效考核系统中的一个评分模块。评分有很多评分的指标,指标下面有子指标,末级
指标下面有具体评分的考核点,每个考核点根据基本的考核量表来评分。同时,评分的界面可以有多种展示,第一种可以点击
每个评分点进去打分,第二种就是给定一个excel表似的试卷一样的页面。而拖放效果的实现,是要求在第一种评分方式下将
被考核人员,直接拖动到对应的分值区域内。
根据业务需求,因此陈黎夫先生的例子,在这里有很多需要扩展的地方。因此这篇文章给对Asp.net Ajax框架客户端实现拖放
有一定了解的朋友。
1)需要实现回拖,就是说已经拖放到评分区域的元素,要可以拖回到原来的区域。
2)可以被投放的区域,也要互相实现拖放
3)在自己的区域拖放要被屏蔽
4)在拖放的时候,相关的数据对象要适当的保存
5)拖放结束后评分的结果要保持到数据库,重新打开这个页面时,得到相应分数的人应该自动被添加相应的得分区域,并且
相应的元素要添加被拖放到行为,被投放的区域添加可以被投放的行为。
综上几点,陈黎夫先生的例子只能限于演示微软的ajax拖放技术,对于实用阶段还有一定的距离。

直观界面如下:

实现本项目的需要需要做到以下几点
1)同样的数据,有多种显示要求。所以整个界面使用xml+xslt技术生成。大家参考我以前关于xml+xslt的文章
2)实现拖放,将陈黎夫先生的例子复制过来改改拖放就可以实现了。
3)需要实现回拖,就是说已经拖放到评分区域的元素,要可以拖回到原来的区域。
将每个区域注册为可以投放的区域

页面初始化时,将要投放的区域循环,添加可以投放的行为
$create(Score.DropPersonBehavior, { "id": id, "name": "personDropBehavior" + id }, null, null, this);

将要拖放的元素添加可以拖放的行为,
$create(Score.DraggablePersonBehavior, { "person": person, "name": "personDragBehavior" + i }, null, null, li);

每个元素拖放结束后,注册为可以拖放的行为
drop: function(dragMode, dataType, data)
{
 if (dataType == 'Person' && data)
 {
     var rectId = parseInt(this.get_id());
     if (rectId == 500)
  Array.add(dropRectSource, data);
     else
  Array.add(dropRect[rectId], data);
     var li = document.createElement("LI");
     li.innerHTML = data.PersonName + '[' + data.OrgName + ']';
     li.className = 'personlistcls';
     li.id = 'li_' + rectId + '_' + data.Id;
     if (this.get_element().getElementsByTagName("LI").length == 0) this.get_element().innerHTML = '';
     this.get_element().appendChild(li);
     this.get_element().style.backgroundColor = "#ffffff";

     $create(Score.DraggablePersonBehavior, { "person": data }, null, null, li);
 }
},
然后将原来的行为注销
onDragEnd: function(canceled)
{
 //if (sourceRectIndex == targetRectIndex) return;
 if (this._visual) this.get_element().parentNode.removeChild(this._visual);
 if (!canceled)
 {
     var sid = parseInt(this.get_element().id.split('_')[1]);
     this.get_element().parentNode.removeChild(this.get_element());
     if (sid == '500')
  Array.remove(dropRectSource, this._person);
     else
  Array.remove(dropRect[sid], this._person);
     this.dispose();
 }
},

4)在拖放的时候,相关的数据对象要适当的保存
在页面初始化时,根据评分区域的多少,循环评分区域,为每个区域添加一个数组。然后伴随每次拖放将数据动态保存到相应的数组中

5)拖放结束后评分的结果要保持到数据库,重新打开这个页面时,得到相应分数的人应该自动被添加相应的得分区域,并且
相应的元素要添加被拖放到行为,被投放的区域添加可以被投放的行为。

在页面pageLoad的时候(客户端)发送ajax请求,将每个已经评分的人员的信息生成xml返回
然后循环子节点。然后根据子节点的信息添加到相应区域,添加相应的行为。


综上总结几点
1)jQuery操作元素比较方便
2)asp.net Ajax对javascript内置的对象的扩展使用比较方便
3)asp.net ajax框架getLocation计算元素位置方法有很大的局限性
4)对于实现拖放其实PreviewDragDrop.js内对IDragSource和IDropTarget接口提供了默认实现的类,和DragDropList等
合理继承这些类,可以极大的减少客户端写大量代码的量。建议大家好好研究PreviewDragDrop.js

主要是js操作,附拖放的js下载:https://files.cnblogs.com/jackhuclan/PersonDragDrop.rar

原文地址:https://www.cnblogs.com/jackhuclan/p/1322036.html