13.自定义菜单
  “自定义菜单”是指向鼠标右键弹出菜单增加菜单项,通过"MenuBeforePopup"事件、调用AddMenu( )函数、以及"MenuClicked"事件,实现了菜单的自定义,整个过程是动态的。
  详细的过程是:当鼠标右键菜单即将要弹出时,Treelist会触发页面的OnEvent(id, "MenuBeforePopup", ...)事件,在这个事件的js中,你可以通过调用AddMenu( )函数向Treelist动态增加菜单项;如果用户选中了你定义的菜单项,Treelist会触发OnEvent(id, "MenuClicked", ...)事件,从而达到了自定义菜单功能的目的.
  在demo中有详细的演示页,相信您一看就明白。
  AddMenu( 参数 )函数中的参数可以是XML串、非XML的文字串,或URL,其规则举例如下:
<items>
<item id="3103" text="热销" icon="buttons.zip#303.ico">
<item id="3104" text="滞销产品" icon="buttons.zip#304.ico">
 <item id="31041" text="库存1" icon="buttons.zip#304.ico" detail="浮动的详细说明,可选"/>
 <item id="31042" text="库存2" enable="false" detail="浮动的详细说明,可选"/>
</item>
</items>
  如果采用非XML的普通串,其举例如下:
//多个菜单项之间以回车符分隔
var s = "id=4001; text=男帽; icon=buttons.zip#301.ico; detail=夏季时装\r\n";
s += "id=4002; text=时髦头巾; icon=buttons.zip#302.ico; detail=优惠直销"
  规则1:如果是XML串,元素名须为item;
  规则2:如果是XML串,item允许有下级item,表示菜单项的子菜单:
  规则3:属性有idtexticonenablecheckeddetail,其中 id 必须 >=3000 .



  14.事件
  Supcan Treelist的OnEvent( id, Event, p1, p2, p3, p4 )事件含义及参数分别如下:
  事件的js用法可参见Demo。
备注1:如果当前列为 Button型 或 editWithButton型, 鼠标点在 button上则为"button";如果列中有多个button,那么分别为"button1"、"button2"...类推.
备注2:EditKeydown和EditChar均为在输入框中的键盘事件,EditKeydown能捕获几乎所有键盘动作,包括非字符的回车、Tab等;而EditChar则以输入的字符为主,包括中文.
您可以执行全局函数 CancelEvent( ) 去阻止继续执行,就如事件没有发生过那样,但不同的ASCII码,您需要在这二个事件中挑选一个执行CancelEvent( ),具体请在演示页“12.事件”中去测试;
备注3:1-Ctrl键也按下了; 2-Shift键也按下了; 3-二者一起按下了.
备注4:格式为handle=[?];asChild=true,例如串"handle=82922093;asChild=true",其中handle的含义为源Treelist的句柄(可通过GetHandle函数获得),如果是自我拖拽,则不出现该项;asChild=true表示作为子孙拖入,如果非子孙、或者当前非树,则不出现该项.



  15.XML提交格式规范
  通过调用函数GetChangedXML( ),能取得输入内容的XML包,使得应用服务器能作相应处理,函数中参数level为提交级别,分如下4种:
  级别0:生成当前全部、最新内容(不包括修改前的原始内容);
  级别1:仅生成被修改过的单元格的内容(包括原始内容);
  级别2:在级别1的基础上,增加被修改过单元的整行内容;
  级别3,内容包含所有行、所有列、修改前后的内容.

  级别0最常用,并且XML规范最简单,如下所示:
<?xml version="1.0" encoding="UTF-8"?">
<!-- id在XML描述文件中定义 -->
<table id="?" level="0" 自定义属性="?" >
 <row>
   <!-- 列名处为真实的列名 -->
   <列名>Text</列名>
   ...
 </row>
 <row ...>
   ...
 </row>
 ...
</table>

  级别1、2、3的内容规定如下:
<?xml version="1.0" encoding="UTF-8"?">
<!-- id、key在XML描述文件中定义 -->
<table id="?" key="?" level="?" 自定义属性="?" >

 <!-- 区域1: 被修改的行 -->
 <modifiedRow>
  <!-- key为该行key列的原始值(被修改前), rowNumber为行号 -->
  <row key="?" rowNumber="?">
   <!-- 列名处为真实的列名, origin为原始值(被修改前),isModified仅用于级别2和级别3, Text处为修改后的值 -->
   <列名 origin="?" isModified="false">Text</列名>
   ...
  </row>
  ...
 </modifiedRow>
 
 <!-- 区域2: 新增行 -->
 <newRow>
  <!-- key为该行key列处输入的值, rowNumber为行号 -->
  <row key="?" rowNumber="?">
   <!-- 列名处为真实的列名, Text处为输入的内容 -->
   <列名>Text</列名>
   ...
  </row>
  ...
 </newRow>
 
 <!-- 区域3: 被删除的行 -->
 <deletedRow>
  <!-- key为该行key列的原始值(被修改前) -->
  <row key="?"></row>
  ...
 </deletedRow>
 
 <!-- 区域4: 未修改过的行(仅用于级别3 时) -->
 <notModifiedRow>
  <!-- 略,和区域1相比只是少了"Origin"属性 -->
 </notModifiedRow>

</table>
警告:应用服务器端开发的程序不应过于依赖级别1/2/3中的origin的内容(被修改前),因为需要考虑并发.