动态载入数据的无刷新TreeView控件(8)

该博客为转载内容,转载自https://www.cnblogs.com/birdshome/archive/2005/04/02/129777.html ,涉及JavaScript和C#两种信息技术领域的编程语言。
    作为一个TreeView控件,显示、操作、动态加载都完成了,接下来最重要的就是怎么和用户代码结合了。事件是一种控件结合用户交互较好的方式,接下来就介绍一下在这个TreeView控件中的事件处理模型及实现。

    我们应该承认,C#的+=和-=方式的事件attach和dettach方式是非常清晰易用的。不过由于JavaScript不支持运算符重载,要实现这样的调用方式非常的困难,因为只有基本的JavaScript数值类型(int, float)才支持+=和-=操作。所以我们考虑按dom那样使用attachEvent的调用方式来实现TreeView控件的事件支持。

    Dom提供的attachEvent和dettachEvent其本质是对一个集合的操作,集合中可以存放一个事件的多个处理器引用。比如:
None.gif  document.attachEvent('onload', handler1);
None.gif document.attachEvent('onload', handler2);
None.gif 
//  . . .
None.gif 
document.attachEvent('onload', handlerN);

    于是我们先实现一个EventHander类,它就是用来存放事件处理器,并处理事件触发的。代码如下:
ExpandedBlockStart.gif ContractedBlock.gif < script  language ="javascript" > dot.gif
InBlock.gif
function EventHandler(sender, action, callback)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
if ( typeof(sender) != 'object' )
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
throw new Error('The first parameter of EventHandler request object "sender".');
ExpandedSubBlockEnd.gif    }

InBlock.gif    
if ( typeof(action) != 'string' )
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
throw new Error('The second parameter of EventHandler request string "action".');
ExpandedSubBlockEnd.gif    }

InBlock.gif    
if ( typeof(callback) != 'function' )
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
throw new Error('The thrid parameter of EventHandler request function "callback".');
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
this.Extends(CollectionBase);
InBlock.gif    
this.m_EventHandlers = this.m_InnerArray;
InBlock.gif
InBlock.gif    
this.m_Action = action;    
InBlock.gif    
this.m_Sender = sender;
InBlock.gif    
this.m_EventArgs = null;
InBlock.gif    
this.AttachHandler(callback);
InBlock.gif
InBlock.gif    
this.toString = function()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return '[class EventHandler]';
ExpandedSubBlockEnd.gif    }
;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gifEventHandler.prototype.Execute 
= function(eventArgs)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
this.m_EventArgs = eventArgs;
InBlock.gif    
for ( var i=0 ; i < this.m_Count ; ++i )
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
var callback = this.Items(i);
InBlock.gif        
if ( typeof(callback) == 'function' )
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            callback(
this.m_Sender, this.m_EventArgs);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif}
;
InBlock.gif
InBlock.gifEventHandler.prototype.AttachHandler 
= function(handler)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
this.Add(handler);
ExpandedSubBlockEnd.gif}
;
InBlock.gif
InBlock.gifEventHandler.prototype.DetachHandler 
= function(handler)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
this.Remove(handler);
ExpandedBlockEnd.gif}
;
None.gif
</ script >
    其实就是个集合,用来放置handlers,并同时触发。

    同时为了调用方便,为Object对象attach了一个AttachEvent的原型方法:
None.gif Object.prototype.AttachEvent  =   function (eventName, eventHandler)
None.gif{
None.gif    
if  (  typeof (eventName)  !=  'string'  ||   typeof (eventHandler)  !=  ' function ' )
None.gif    {
None.gif        
return   new  Error('eventName, eventHandler. Error parameters type.');
None.gif    }
None.gif    
if  ( eventName[ 0 !=  'e'  ||  eventName[ 1 !=  '_' )
None.gif    {
None.gif        eventName 
=  'e_'  +  eventName;
None.gif    }
None.gif    
var  evt  =   this [eventName];
None.gif    
if  (  typeof (evt)  !=  'undefined' )
None.gif    {
None.gif        
if  ( __typeof__(evt)  ==  'EventHandler' )
None.gif        {
None.gif            evt.AttachHandler(eventHandler);
None.gif        }
None.gif        
else
None.gif        {
None.gif            
this [eventName]  =   new  EventHandler( this , eventName, eventHandler);
None.gif        }
None.gif    }
None.gif};

    定义好了事件的处理模型,我们在TreeView中怎么使用呢?下面一Collapse操作为例,如果我们要再TreeNode执行了Collapse后做一些用户自定义的事情,比如修改图标什么的。于是我们在TreeNode中定一个事件,名叫:e_Collapsed。修改Collpase方法如下:
None.gif TreeNode.prototype.Collapse  =   function ()
None.gif{
None.gif    
var  elmtNode  =   this .m_Element;
None.gif    
var  childTree  =  elmtNode.nextSibling;
None.gif    
if  ( childTree )
None.gif    {
None.gif        childTree.style.display 
=  'none';
None.gif        
this .m_IsChildExpanded  =   false ;
None.gif        elmtNode.OpIcon.src 
=  TreeStyle.OpIcon( this .GetOpIconName());
None.gif        
if  (  this .e_Collapsed )
None.gif        {
None.gif            
this .e_Collapsed.Execute('collapse');
None.gif        }
None.gif    }     
None.gif};

    其实就是添加了一个触发eventHandlers的调用 this .e_Collapsed.Execute('collapse');。使用这个event和使用DHMTL的dom中的attachEvent一样,并且也支持attach多个eventHandler到一个事件上。
None.gif  var  node  =   new  TreeNode('TestNode');
None.gif node.AttachEvent('Collapsed', fnCollapsed);
    // 这里把事件名写成'Collapsed'和'e_Collapsed'是完全一样的,AttachEvent内部做了处理。

    eventHandler就是一个普通的函数,只是它的arguments[0]和arguments[1]是sender和eventArgs。上面示例的处理函数示例为:
None.gif  function  fnCollapsed(sender, e)
None.gif {
None.gif     
var  node  =  sender;
None.gif     node.SetCustomizeIcon('E:\\Working\\Private\\TreeView\\Images\\close.gif');
None.gif     status 
=  'collapsed status: '  +  e  +  ', '  +  sender.m_Id;
None.gif }
    作用是把当前TreeNode的图标换为'close.gif'。

    使用上面的方法,我们可以为TreeNode实现以下常用的事件:
None.gif  this .e_Clicked  =   null ;
None.gif 
this .e_SelectedChanged  =   null ;
None.gif 
this .e_CheckedChanged  =   null ;
None.gif 
this .e_NodeCreating  =   null ;
None.gif 
this .e_Expanded  =   null ;
None.gif 
this .e_Collapsed  =   null ;
None.gif 
this .e_Appended  =   null ;

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

    to be continued ...

转载于:https://www.cnblogs.com/birdshome/archive/2005/04/02/129777.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值