在DataGrid的实际使用过程中,有时候会需要将前面几列锁住,或者前几行锁住,就像Excel的表设计一样。在滚动条拖动的时候能始终保持前面锁定的列显示在界面中。
在flex的DataGrid设计中实际上已经考虑到了这个功能。属性lockedColumnCount和lockedRowCount就是实现这个功能的最快捷径。但是lockedColumnCount属性却不能解决始终保持某一列如Id保持在第一列,虽然我们可以设置Id列的draggable=false,但我们可以拖动后面的列到Id列的前面,从而打破这个规则,这是我们不愿看到的结果。
在这个例子中我们通过对DataGrid的扩展和重写,对DataGridColumn列的拖动后放下的函数处理进行一个限制判断,对于放下的索引号小于等于我们锁定列数,那么我们不让其交换列。原理就这么简单,但这里有一个问题就是函数的作用域问题。函数shiftColumns就是处理交换列的函数,改函数的作用域为mx_internal,因此这里做了一个对mx_internal引用的问题。
import mx.core.mx_internal;
use namespace mx_internal;
代码:
LockableDataGrid.as
package cwmlib
{
import flash.events.Event;
import mx.controls.DataGrid;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.core.mx_internal;
use namespace mx_internal;
public class LockableDataGrid extends DataGrid
{
public function LockableDataGrid()
{
super();
}
/**
* do not allow the locked column shift and other column can not shift before these columns
*/
override mx_internal function shiftColumns(oldIndex:int, newIndex:int,
trigger:Event = null):void
{
if(newIndex < this.lockedColumnCount){
return;
}
super.shiftColumns(oldIndex,newIndex,trigger);
}
override protected function createChildren():void
{
super.createChildren();
for(var i:int = 0; i < this.columns.length; i ++){
var c:DataGridColumn = this.columns[i] as DataGridColumn;
if(i < this.lockedColumnCount){
c.draggable = false;
}
}
}
}
}
//测试代码LockableDataGridApp.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
xmlns:cwmlib="cwmlib.*">
<mx:Script>
<![CDATA[
[Bindable]
private var dp:XMLList =
<><item id='100' name='Name A' city='Shanghai' email='emailA@gmail.com' description='desc 1'/>
<item id='101' name='Name B' city='Beijing' email='emailB@gmail.com' description='desc 2'/>
<item id='102' name='Name C' city='Hangzhou' email='emailC@gmail.com' description='desc 3'/>
<item id='103' name='Name D' city='Hongkong' email='emailD@gmail.com' description='desc 4'/>
<item id='104' name='Name E' city='Boston' email='emailE@gmail.com' description='desc 5'/>
<item id='105' name='Name F' city='Shenzhen' email='emailF@gmail.com' description='desc 6'/>
<item id='106' name='Name G' city='Tianjin' email='emailG@gmail.com' description='desc 7'/>
<item id='107' name='Name H' city='Chongqing' email='emailH@gmail.com' description='desc 8'/>
<item id='108' name='Name I' city='New York' email='emailI@gmail.com' description='desc 9'/>
</>;
]]>
</mx:Script>
<mx:Label text="Totally Locked Column, can not shift move the locked column"/>
<cwmlib:LockableDataGrid width="500" lockedRowCount="1" lockedColumnCount="1" horizontalScrollPolicy="on" dataProvider="{dp}">
<cwmlib:columns>
<mx:DataGridColumn dataField="@id" headerText="Id" width="100"/>
<mx:DataGridColumn dataField="@name" headerText="Name" width="100"/>
<mx:DataGridColumn dataField="@city" headerText="City" width="200"/>
<mx:DataGridColumn dataField="@email" headerText="Email" width="200"/>
<mx:DataGridColumn dataField="@description" headerText="Description" width="300"/>
</cwmlib:columns>
</cwmlib:LockableDataGrid>
<mx:Label text="Flex Default Locked Column, can shift move the locked column"/>
<mx:Label text="Even if set the locked column draggable=false, also can move other column to the first column"/>
<mx:DataGrid width="500" lockedRowCount="1" lockedColumnCount="1" horizontalScrollPolicy="on" dataProvider="{dp}">
<mx:columns>
<mx:DataGridColumn dataField="@id" draggable="false" headerText="Id" width="100"/>
<mx:DataGridColumn dataField="@name" headerText="Name" width="100"/>
<mx:DataGridColumn dataField="@city" headerText="City" width="200"/>
<mx:DataGridColumn dataField="@email" headerText="Email" width="200"/>
<mx:DataGridColumn dataField="@description" headerText="Description" width="300"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
感谢Zhenglei对该DataGrid功能的扩展。