作为一个TreeView控件,显示、操作、动态加载都完成了,接下来最重要的就是怎么和用户代码结合了。事件是一种控件结合用户交互较好的方式,接下来就介绍一下在这个TreeView控件中的事件处理模型及实现。
我们应该承认,C#的+=和-=方式的事件attach和dettach方式是非常清晰易用的。不过由于JavaScript不支持运算符重载,要实现这样的调用方式非常的困难,因为只有基本的JavaScript数值类型(int, float)才支持+=和-=操作。所以我们考虑按dom那样使用attachEvent的调用方式来实现TreeView控件的事件支持。
Dom提供的attachEvent和dettachEvent其本质是对一个集合的操作,集合中可以存放一个事件的多个处理器引用。比如:
document.attachEvent('onload', handler1);
document.attachEvent('onload', handler2);
//
. . .
document.attachEvent('onload', handlerN);
于是我们先实现一个EventHander类,它就是用来存放事件处理器,并处理事件触发的。代码如下:
<
script
language
="javascript"
>
function EventHandler(sender, action, callback)


{
if ( typeof(sender) != 'object' )

{
throw new Error('The first parameter of EventHandler request object "sender".');
}
if ( typeof(action) != 'string' )

{
throw new Error('The second parameter of EventHandler request string "action".');
}
if ( typeof(callback) != 'function' )

{
throw new Error('The thrid parameter of EventHandler request function "callback".');
}

this.Extends(CollectionBase);
this.m_EventHandlers = this.m_InnerArray;

this.m_Action = action;
this.m_Sender = sender;
this.m_EventArgs = null;
this.AttachHandler(callback);

this.toString = function()

{
return '[class EventHandler]';
};
}

EventHandler.prototype.Execute = function(eventArgs)


{
this.m_EventArgs = eventArgs;
for ( var i=0 ; i < this.m_Count ; ++i )

{
var callback = this.Items(i);
if ( typeof(callback) == 'function' )

{
callback(this.m_Sender, this.m_EventArgs);
}
}
};

EventHandler.prototype.AttachHandler = function(handler)


{
this.Add(handler);
};

EventHandler.prototype.DetachHandler = function(handler)


{
this.Remove(handler);
};
</
script
>
其实就是个集合,用来放置handlers,并同时触发。
同时为了调用方便,为Object对象attach了一个AttachEvent的原型方法:
Object.prototype.AttachEvent
=
function
(eventName, eventHandler)
{
if
(
typeof
(eventName)
!=
'string'
||
typeof
(eventHandler)
!=
'
function
' )
{
return
new
Error('eventName, eventHandler. Error parameters type.');
}
if
( eventName[
0
]
!=
'e'
||
eventName[
1
]
!=
'_' )
{
eventName
=
'e_'
+
eventName;
}
var
evt
=
this
[eventName];
if
(
typeof
(evt)
!=
'undefined' )
{
if
( __typeof__(evt)
==
'EventHandler' )
{
evt.AttachHandler(eventHandler);
}
else
{
this
[eventName]
=
new
EventHandler(
this
, eventName, eventHandler);
}
}
};
定义好了事件的处理模型,我们在TreeView中怎么使用呢?下面一Collapse操作为例,如果我们要再TreeNode执行了Collapse后做一些用户自定义的事情,比如修改图标什么的。于是我们在TreeNode中定一个事件,名叫:e_Collapsed。修改Collpase方法如下:
TreeNode.prototype.Collapse
=
function
()
{
var
elmtNode
=
this
.m_Element;
var
childTree
=
elmtNode.nextSibling;
if
( childTree )
{
childTree.style.display
=
'none';
this
.m_IsChildExpanded
=
false
;
elmtNode.OpIcon.src
=
TreeStyle.OpIcon(
this
.GetOpIconName());
if
(
this
.e_Collapsed )
{
this
.e_Collapsed.Execute('collapse');
}
}
};
其实就是添加了一个触发eventHandlers的调用 this .e_Collapsed.Execute('collapse');。使用这个event和使用DHMTL的dom中的attachEvent一样,并且也支持attach多个eventHandler到一个事件上。
var
node
=
new
TreeNode('TestNode');
node.AttachEvent('Collapsed', fnCollapsed);
// 这里把事件名写成'Collapsed'和'e_Collapsed'是完全一样的,AttachEvent内部做了处理。
eventHandler就是一个普通的函数,只是它的arguments[0]和arguments[1]是sender和eventArgs。上面示例的处理函数示例为:
function
fnCollapsed(sender, e)
{
var
node
=
sender;
node.SetCustomizeIcon('E://Working//Private//TreeView//Images//close.gif');
status
=
'collapsed status: '
+
e
+
', '
+
sender.m_Id;
}
作用是把当前TreeNode的图标换为'close.gif'。
使用上面的方法,我们可以为TreeNode实现以下常用的事件:
this
.e_Clicked
=
null
;
this
.e_SelectedChanged
=
null
;
this
.e_CheckedChanged
=
null
;
this
.e_NodeCreating
=
null
;
this
.e_Expanded
=
null
;
this
.e_Collapsed
=
null
;
this
.e_Appended
=
null
;
这些事件在没有AttachEvent之前不会产生任何的处理代价,除了一个if判断。
to be continued ...
我们应该承认,C#的+=和-=方式的事件attach和dettach方式是非常清晰易用的。不过由于JavaScript不支持运算符重载,要实现这样的调用方式非常的困难,因为只有基本的JavaScript数值类型(int, float)才支持+=和-=操作。所以我们考虑按dom那样使用attachEvent的调用方式来实现TreeView控件的事件支持。
Dom提供的attachEvent和dettachEvent其本质是对一个集合的操作,集合中可以存放一个事件的多个处理器引用。比如:




于是我们先实现一个EventHander类,它就是用来存放事件处理器,并处理事件触发的。代码如下:











































































同时为了调用方便,为Object对象attach了一个AttachEvent的原型方法:























定义好了事件的处理模型,我们在TreeView中怎么使用呢?下面一Collapse操作为例,如果我们要再TreeNode执行了Collapse后做一些用户自定义的事情,比如修改图标什么的。于是我们在TreeNode中定一个事件,名叫:e_Collapsed。修改Collpase方法如下:















其实就是添加了一个触发eventHandlers的调用 this .e_Collapsed.Execute('collapse');。使用这个event和使用DHMTL的dom中的attachEvent一样,并且也支持attach多个eventHandler到一个事件上。


eventHandler就是一个普通的函数,只是它的arguments[0]和arguments[1]是sender和eventArgs。上面示例的处理函数示例为:






使用上面的方法,我们可以为TreeNode实现以下常用的事件:







这些事件在没有AttachEvent之前不会产生任何的处理代价,除了一个if判断。
to be continued ...