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

作为一个TreeView控件,显示、操作、动态加载都完成了,接下来最重要的就是怎么和用户代码结合了。事件是一种控件结合用户交互较好的方式,接下来就介绍一下在这个TreeView控件中的事件处理模型及实现。

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

    Dom提供的attachEvent和dettachEvent其本质是对一个集合的操作,集合中可以存放一个事件的多个处理器引用。比如:
动态载入数据的无刷新TreeView控件(8) document.attachEvent('onload', handler1);
动态载入数据的无刷新TreeView控件(8) document.attachEvent('onload', handler2);
动态载入数据的无刷新TreeView控件(8) // . . .
动态载入数据的无刷新TreeView控件(8) 
document.attachEvent('onload', handlerN);

    于是我们先实现一个EventHander类,它就是用来存放事件处理器,并处理事件触发的。代码如下:
动态载入数据的无刷新TreeView控件(8)<script language="javascript">动态载入数据的无刷新TreeView控件(8)</script>
    其实就是个集合,用来放置handlers,并同时触发。

    同时为了调用方便,为Object对象attach了一个AttachEvent的原型方法:
动态载入数据的无刷新TreeView控件(8)Object.prototype.AttachEvent = function(eventName, eventHandler)
动态载入数据的无刷新TreeView控件(8){
动态载入数据的无刷新TreeView控件(8)    if ( typeof(eventName) != 'string' || typeof(eventHandler) != 'function' )
动态载入数据的无刷新TreeView控件(8)    {
动态载入数据的无刷新TreeView控件(8)        return new Error('eventName, eventHandler. Error parameters type.');
动态载入数据的无刷新TreeView控件(8)    }
动态载入数据的无刷新TreeView控件(8)    if ( eventName[0] != 'e' || eventName[1] != '_' )
动态载入数据的无刷新TreeView控件(8)    {
动态载入数据的无刷新TreeView控件(8)        eventName = 'e_' + eventName;
动态载入数据的无刷新TreeView控件(8)    }
动态载入数据的无刷新TreeView控件(8)    var evt = this[eventName];
动态载入数据的无刷新TreeView控件(8)    if ( typeof(evt) != 'undefined' )
动态载入数据的无刷新TreeView控件(8)    {
动态载入数据的无刷新TreeView控件(8)        if ( __typeof__(evt) == 'EventHandler' )
动态载入数据的无刷新TreeView控件(8)        {
动态载入数据的无刷新TreeView控件(8)            evt.AttachHandler(eventHandler);
动态载入数据的无刷新TreeView控件(8)        }
动态载入数据的无刷新TreeView控件(8)        else
动态载入数据的无刷新TreeView控件(8)        {
动态载入数据的无刷新TreeView控件(8)            this[eventName] = new EventHandler(this, eventName, eventHandler);
动态载入数据的无刷新TreeView控件(8)        }
动态载入数据的无刷新TreeView控件(8)    }
动态载入数据的无刷新TreeView控件(8)};

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

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

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

    使用上面的方法,我们可以为TreeNode实现以下常用的事件:
动态载入数据的无刷新TreeView控件(8) this.e_Clicked = null;
动态载入数据的无刷新TreeView控件(8) this.e_SelectedChanged = null;
动态载入数据的无刷新TreeView控件(8) this.e_CheckedChanged = null;
动态载入数据的无刷新TreeView控件(8) this.e_NodeCreating = null;
动态载入数据的无刷新TreeView控件(8) this.e_Expanded = null;
动态载入数据的无刷新TreeView控件(8) this.e_Collapsed = null;
动态载入数据的无刷新TreeView控件(8) this.e_Appended = null;

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

    to be continued ...


本文转自博客园鸟食轩的博客,原文链接:http://www.cnblogs.com/birdshome/,如需转载请自行联系原博主。

上一篇:如何才能以更低投入帮助工业企业建立一座柔性制造智能工厂?


下一篇:2.mybatis入门实例 连接数据库进行查询