[EXT]Ext、以及Coolite下实现表格锁定列和多行表头

转载:http://www.cnblogs.com/zhujiechang/archive/2009/11/10/1599930.html

      这段时间我们的项目中采用了Coolite来做富客户端,Coolite目前的版本是0.8.1,它所采用的Ext版本是2.2.1,因此下面主要是说明 在这个版本下所实现的锁定列和多行表头,需要说明的是Ext在2.0版本以后就不自带锁定列功能了,只能自己实现,中国人的习惯和国外的不太一样,喜欢表 格化得数据,而且形式又多种,表格最基本的功能之一,就是要锁定列和多行表头,而这两项又是Coolite和Ext所提供的组件中所没有直接包含的,虽然 他们这两个框架没有提供,但依然要说的是Ext的js功能很强大, Coolite为Ext在ASP.NET上的应用封装了绝大多数功能,还扩展了一部分,庞大的功能模块,非常不错,可以和官方开源封装的java版 GWT2.0媲美。
     看了些废话,讲入主题了,看下效果图:

    

     实现锁定列目前较为常见的是继承Grid,然后重写模块,实现双表格,下面的示例是采用MeDavid所实现的锁定列方式,版本为[Update 5],Ext的代码很长就贴点主要和修正的,例子在后面有完整提供。Ext为这些控件都提供了一个模板的方式以供重写,就是重写了主模板.

 


 1 initTemplates : function(){
 2         if(!this.templates){
 3             this.templates = {};
 4         }
 5         if(!this.templates.master){
 6             this.templates.master = new Ext.Template(
 7                 '<div class="x-grid3" hidefocus="true">',
 8                     '<div class="x-grid3-locked">',
 9                         '<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset">{lockedHeader}</div></div><div class="x-clear"></div></div>',
10                         '<div class="x-grid3-scroller"><div class="x-grid3-body">{lockedBody}</div><div class="x-grid3-scroll-spacer"></div></div>',
11                     '</div>',
12                     '<div class="x-grid3-viewport">',
13                         '<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset">{header}</div></div><div class="x-clear"></div></div>',
14                         '<div class="x-grid3-scroller"><div class="x-grid3-body">{body}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',
15                     '</div>',
16                     '<div class="x-grid3-resize-marker"> </div>',
17                     '<div class="x-grid3-resize-proxy"> </div>',
18                 '</div>'
19             );
20         }
21         Ext.grid.LockingGridView.superclass.initTemplates.call(this);
22     },
23 

     同时为ColumnModel增加getTotalLockedWidth方法,原有[Update 5]中的脚本中Ext.grid.LockingColumnModel要去掉。


1 Ext.grid.ColumnModel.prototype.getTotalLockedWidth=function(){
2         var totalWidth = 0;
3         for(var i = 0; i < this.config.length; i++){
4             if(this.isLocked(i) && !this.isHidden(i)){
5                 totalWidth += this.getColumnWidth(i);
6             }
7         }
8         return totalWidth;
9     };

      另外,版本为[Update 5]目前支持行选择模式有点BUG,就是在获得焦点时行会移动,这是因为没有重新定位造成的,在Ext.grid.LockingGridView中加入以下方法即可修正。

 


1 getResolvedXY : function(resolved){
2         if(!resolved){
3             return null;
4         }
5         var c = resolved.cell, r = resolved.row;
6         return c ? Ext.fly(c).getXY() : [this.scroller.getX(), Ext.fly(r).getY()];
7     },
8 

     多行表头分别对应有两个文件,一个是针对有锁定列的表格,一个是针对没有锁定列的表格,两个表格输出的对象是不一样的,要经过判断来输出不一样的值,至于实现的方式大家看下代码就知道了。

     下面把它融入进Coolite中。新建一个ExtGridPanel继承自GridPanel,然后重写OnPreRender如下:

 


 1 protected override void OnPreRender(EventArgs e)
 2         {
 3             //判断是否有锁定列
 4             bool haveLock=false;
 5             ExtColumn extcolumn;
 6             int i;
 7             for (i = 0; i < ColumnModel.Columns.Count; i++)
 8             {
 9                 extcolumn = ColumnModel.Columns[i] as ExtColumn;
10                 if (extcolumn == null)
11                     break;
12                 else if (extcolumn.Locked)
13                 {
14                     haveLock = true;
15                     break;
16                 }
17             }            
18             //判断是否有多行表头            
19             foreach (Plugin plugin in Plugins)
20             {
21                 if (plugin is ExtGroupHeaderGrid)
22                 {
23                     //如果表格是由锁定的,那一样通知插件也是要求锁定的
24                     //这里用一个属性进行区分
25                     ((ExtGroupHeaderGrid)plugin).Locked = haveLock;                    
26                     break;
27                 }
28             }
29 
30             System.ComponentModel.AttributeCollection attrscoll = TypeDescriptor.GetAttributes(thistrue);
31 
32             //注册js
33             if (haveLock)
34             {
35                 //锁定列之前的列也必须锁定
36                 for (int j = 0; j < i; j++)
37                 {
38                     extcolumn = ColumnModel.Columns[j] as ExtColumn;
39                     if (extcolumn != null)
40                         extcolumn.Locked = haveLock;                    
41                 }
42                 ((InstanceOfAttribute)attrscoll[typeof(InstanceOfAttribute)]).ClassName = "Ext.grid.LockingEditorGridPanel";
43                 ScriptManager.RegisterClientScriptInclude(base.GetType(), "CDPFLibrary.Build.extjs.Grid.LockingGridPanel.js");
44             }
45             else
46             {
47                 ((InstanceOfAttribute)attrscoll[typeof(InstanceOfAttribute)]).ClassName = "Coolite.Ext.GridPanel";
48             }
49              
50             base.OnPreRender(e);
51         }

     同时新增了几个类,新增类如下:ExColumnModel、ExtColumn、ExtGridPanel、ExtGroupHeaderGrid、 ExtRow、ExtRowCollection、ExtRows、ExtRowsCollection这些,具体代码都在源码中可以自己分析。
因为同一个表格同时要支持锁定列和非锁定列,因为功能不同输出的js也不一样,那么InstanceOfAttribute的ClassName类名要进行变动,所以要采用TypeDescriptor.GetAttributes来取得属性,这样可以保存当前实例所进行修改过后的自定义属性值,而用Type. GetCustomAttributes只能取得实例定义时的值,不能获得当前实例改动后的值,这一点要在Coolite.Ext.Web程序集的WebControl_Helpers类的GetClientConstructor方法和InstanceOf属性中进行修改,个人认为它是一个明显的BUG。

     其实涉及的变动的地方还挺多,上面仅仅是关键点,源码随文章发布,Coolite的源码可以去官方下来,下面也有链接。

     下载:锁定列和多表头源码    Coolite源码0.8.1
     项目需要用Vs2008打开,需要ASP.NET3.5支持,欢迎发表意见。

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏