ExtenderControl是AJAX.NET框架里扩展控件的基类,比如ControlToolKit里的一些扩展控件就是从这个基类派生而来。这也是AJAX.NET框架提供给用户在客户端定义Behavior的一种方式。这种客户端的Behavior主要用于扩展服务器控件的行为,让服务器控件有更多的客户端功能,提供更好的用户体验。而这种扩展控件的方式是不改变原有服务器的行为,只是新增功能,也算是一种装饰模式。
这里所做的Extender控件的功能是实现服务器控件在页面上可被拖放,当然这个功能在强大的AJAX.NET的预览版本里已经有了很好的实现,我这里所做的也只是简单的拖放。基本的思路是采用AJAX正式版框架里定义Behavior的方式,然后定义一些模拟拖放的事件。实现拖放的逻辑也很简单,当需要拖放的对象被点击之后,给body添加mousemove和mouseup事件,具体的移动逻辑在mousemove里实现,mouseup则清空body的事件,拖放结束。这个逻辑也是按照<<javascript高级编程>>书上介绍的方法,没有特别深奥的东西。说白了就是演练一下定义extender控件,把一些老的东西重新包装一下。除了简单的拖放逻辑,还提供了一个属性dragCssClass,就是在拖放的时候的样式,比如设置鼠标为move等等。具体代码如下
1.首先定义个extender继承ExtenderControl,当然这个要引用AJAX.NET的System.Web.Extension.dll.要指定
[TargetControlType(typeof(Control))]类型,还需要注册脚本,脚本当然也是嵌入到资源中的。基类方法的作用请看AJAX.NET提供的帮助。
DragExtender
1[assembly: WebResource("AjaxControl.DragBehavior.js", "text/javascript")]
2namespace AjaxControl
3{
4 [TargetControlType(typeof(Control))]
5 public class DragExtender : ExtenderControl
6 {
7 private string _dragCssClass;
8 /**//// <summary>
9 /// 拖动时的样式
10 /// </summary>
11 public string DragCssClass
12 {
13 get { return _dragCssClass; }
14 set { _dragCssClass = value; }
15 }
16
17 protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl)
18 {
19 ScriptBehaviorDescriptor descriptor = new ScriptBehaviorDescriptor("Shenba.DragBehavior", targetControl.ClientID);
20 descriptor.AddProperty("dragCssClass", this._dragCssClass);
21 return new ScriptBehaviorDescriptor[] { descriptor };
22 }
23
24 protected override IEnumerable<ScriptReference> GetScriptReferences()
25 {
26 string jsPath = ResolveClientUrl("AjaxControl.DragBehavior.js");
27 ScriptReference reference = new ScriptReference(jsPath);
28 return new ScriptReference[] { reference };
29 }
30
31 protected override void OnPreRender(EventArgs e)
32 {
33 if (!this.DesignMode)
34 {
35 // 将脚本添加到scriptmanager的脚本引用中
36 ScriptManager sm = ScriptManager.GetCurrent(Page);
37 if (sm == null)
38 {
39 throw new HttpException("a scriptmanager is required in the page.");
40 }
41 sm.Scripts.Add(new ScriptReference("AjaxControl.DragBehavior.js", "AjaxControl"));
42 }
43 base.OnPreRender(e);
44 }
45 }
46}
47
2.接下来是js的脚本,也是核心逻辑的一部分
DragBehavior.js
1Type.registerNamespace("Shenba");
2
3Shenba.DragBehavior = function (element)
4{
5 Shenba.DragBehavior.initializeBase(this, [element]);
6 // 分别用于记录鼠标落点与目标对象坐标的偏差
7 this._diffX = 0;
8 this._diffY = 0;
9}
10
11Shenba.DragBehavior.prototype = {
12 initialize : function ()
13 {
14 Shenba.DragBehavior.callBaseMethod(this, "initialize");
15
16 // 将目标对象的定位转化成绝对定位
17 this.get_element().style.position = "absolute";
18 this._mouseDownHandler = Function.createDelegate(this, this._onMouseDown);
19 $addHandler(this.get_element(), "mousedown", this._mouseDownHandler);
20 },
21
22 set_dragCssClass : function(value)
23 {
24 if (this._dragCssClass !== value)
25 {
26 this._dragCssClass = value;
27 this.raisePropertyChanged("dragCssClass");
28 }
29 },
30 get_dragCssClass : function()
31 {
32 return this._dragCssClass;
33 },
34
35 _onMouseDown : function (e)
36 {
37 var ele = this.get_element();
38 this._diffX = e.clientX - ele.offsetLeft;
39 this._diffY = e.clientY - ele.offsetTop;
40
41 // 给body添加mouseMove合mouseUp事件
42 this._mouseMoveHandler = Function.createDelegate(this, this._onMouseMove);
43 $addHandler(document.body, "mousemove", this._mouseMoveHandler);
44 this._mouseUpHandler = Function.createDelegate(this, this._onMouseUp);
45 $addHandler(document.body, "mouseup", this._mouseUpHandler);
46
47 this.get_element().className = this._dragCssClass;
48 },
49 _onMouseMove : function (e)
50 {
51 var ele = this.get_element();
52 ele.style.left = e.clientX - this._diffX;
53 ele.style.top = e.clientY - this._diffY;
54 },
55 _onMouseUp : function ()
56 {
57 // 鼠标释放之后删除body的事件
58 $removeHandler(document.body, "mousemove", this._mouseMoveHandler);
59 $removeHandler(document.body, "mouseup", this._mouseUpHandler);
60 this._diffX = 0;
61 this._diffY = 0;
62 this.get_element().className = "";
63 },
64
65 dispose : function ()
66 {
67 $clearHandlers(document.body);
68 $clearHandlers(this.get_element());
69 Shenba.DragBehavior.callBaseMethod(this, "dispose");
70 }
71}
72
73Shenba.DragBehavior.descriptor = {
74 properties: [ {name: "dragCssClass", type: String} ]
75}
76
77Shenba.DragBehavior.registerClass("Shenba.DragBehavior", Sys.UI.Behavior);
78
79if (typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
80
81
82
最后在页面中调用就非常的简单,记得添加scriptmanager即可
Page
1<%@ Register Assembly="AjaxControl" Namespace="AjaxControl" TagPrefix="shenba" %>
2<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
3 <div>
4 <asp:Calendar ID="ca" runat="server"></asp:Calendar>
5 <shenba:DragExtender TargetControlID="ca" DragCssClass="drag" ID="dragExtender1" runat="server"/>
6 </div>
目前实现的只是简单拖动,不能像profile那样保存起来,有空再研究下。
完整代码