初学FLEX时,需要在AS里动态生成DataGrid,结果搞了很久才搞明白怎么把用MXML写出来的DataGrid改成用AS写出来,其中最主要的就是自定义itemEditor、itemRender怎么写,写篇东西整理总结下。
先看看下面这段代码:
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
mx:Application
xmlns:mx
=
"http://www.adobe.com/2006/mxml"
layout
=
"absolute"
>
<
mx:Script
>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.DataGrid;
import mx.events.ListEvent;
[Bindable]
private var dgDataArr:Array = [{name: "Jon", job: "officer"},
{name: "James", job: "seller"},
{name: "Jodon", job: "manager"}];
private function itemClickHandler(e:ListEvent):void
{
trace(e.target);
}
]]>
</
mx:Script
>
<
mx:Component
id
=
"comboboxEditor"
>
<
mx:ComboBox
dataProvider
=
"{dt}"
editable
=
"true"
>
<
mx:Script
>
<![CDATA[
private var dt:Array = ["officer", "seller", "manager"];
]]>
</
mx:Script
>
</
mx:ComboBox
>
</
mx:Component
>
<
mx:DataGrid
width
=
"100%"
x
=
"10"
y
=
"20"
fontSize
=
"14"
dataProvider
=
"{dgDataArr}"
editable
=
"true"
itemClick
=
"itemClickHandler(event)"
>
<
mx:columns
>
<
mx:DataGridColumn
dataField
=
"name"
editable
=
"false"
/>
<
mx:DataGridColumn
dataField
=
"job"
itemEditor
=
"{comboboxEditor}"
>
</
mx:DataGridColumn
>
</
mx:columns
>
</
mx:DataGrid
>
</
mx:Application
>
|
代码实现的是创建一个DataGrid,其中job栏可以编辑,并且编辑器是自定义的一个ComboBox。效果如下:
现在看怎么用AS代替MXML创建同样的DataGrid。
<
mx:DataGrid
x
=
"10"
y
=
"20"
editable
=
"true"
width
=
"100%"
fontSize
=
"14"
dataProvider
=
"{dgDataArr}"
itemClick
=
"itemClickHandler(event)"
></
mx:DataGrid
>
|
写成AS大概是这样:
private
function
init():
void
{
var
dgData:ArrayCollection =
new
ArrayCollection(dgDataArr);
var
dataGrid:DataGrid =
new
DataGrid();
dataGrid.x =
10
;
dataGrid.y =
20
;
dataGrid.editable =
true
;
dataGrid.percentWidth =
100
;
dataGrid.setStyle(
"fontSize"
,
14
);
dataGrid.dataProvider = dgDataArr;
dataGrid.addEventListener(ListEvent.ITEM_CLICK, itemClickHandler);
addChild(dataGrid);
}
|
可以看到,在MXML里统一使用XX=”"的形式,但写成AS却各有不同。我没看过书,刚开始也迷惑,怎么就不能dataGrid.fontSize = 14这样写呢。
看下文档,才知道,每个MXML组件后面的属性分三种:
1.Properties 正常属性,如x y width等,写成AS是 dataGrid.x = 10
2.Styles 样式属性,如fontSize backgroundColor等,需要通过setStyle()设置,如dataGrid.setStyle(“fontSize”, 14);,也可以通过设置其styleName属性绑定到页面的一个css里。如:
dataGrid.styleName =
"datagrid"
;
|
<
mx:Style
>
.datagrid{
fontSize:14;
}
</
mx:Style
>
|
3.Events 事件属性,AS要使用事件侦听,itemClick=”itemClickHandler(event)”对应的是如dataGrid.addEventListener(ListEvent.ITEM_CLICK, itemClickHandler);。具体哪个属性对应哪个事件,就要查文档了。
其中width有点特殊,如果想设置百分比的宽度,不能用 dataGrid.width = “100%”,需要设置percentWidth,实际上在MXML设置width时如果有百分号,数值会传给percentWidth而不是width
还有一个属性比较特殊,就是dataProvider,它是一个实现ICollectionView接口的东西。如果传入的是Array,会自动转成ArrayCollection,如果是XMLList会转成XMLListCollection。这里直接传入一个ArrayCollection,是为了之后使用不同过滤函数时不用调用dataGrid.dataProvider而直接用dgData,如dgData.filterFunction = myFilterFunction
var
columns:
Array
=
new
Array
();
var
col:DataGridColumn;
for
(
var
i:*
in
dgDataArr[
0
] ) {
col =
new
DataGridColumn(i);
if
( i ==
"name"
) col.editable =
false
;
columns.push(col);
}
dataGrid.columns = columns;
|
这里只有两栏属性,用for in有点浪费了,这里只是示例。一般用AS写DataGrid都是动态生成的,数据也不确定,都用遍历添加栏。
传给itemRender和itemEditor都必须是一个实现IFactory接口的东西,IFactory接口很简单,只有一个newInstance()函数,DataGrid在渲染每一栏和每一栏的编辑器时都调用这个函数,返回一个新的渲染器。DataGrid默认的渲染器是DataGridItemRenderer,编辑的渲染器是TextInput。用下面的语句就可以把某一栏的编辑器设定为ComboBox:
var
comboboxFactory:ClassFactory =
new
ClassFactory(ComboBox);
col.itemEditor = comboboxFactory;
|
ClassFactory是实现了IFactory接口的类,上面这样设定后,每次col这一栏编辑的时候就会调用comboboxFactory.newInstance()生成一个ComboBox实例。
如果就只是上面那样设置,结果就是编辑时跳出来的ComboBox没有值,也不允许编辑,怎样传值进去呢?
ClassFactory有个properties属性可以让你传值给每一个ComboBox:
comboboxFactory.properties = { dataProvider: [
"officer"
,
"seller"
,
"manager"
], editable:
true
};
|
编辑后,DataGrid会默认把编辑器的text属性值保存到dataProvider里,并传送到itemRender。如果这里的编辑器没有text属性,例如NumericStepper,就需要给栏目设定editorDataField属性,指定编辑后该去哪里取修改过的值。例如:col.editorDataField = “value”
如果想要有更大的自由度,也可以自己写一个实现IFactory接口的类,在newInstance()里返回一个实例就行了:
package
{
import
mx.controls.ComboBox;
import
mx.core.IFactory;
public
class
CustomComboBox
implements
IFactory
{
private
var
customData:
Array
= [
"officer"
,
"seller"
,
"manager"
];
public
function
CustomComboBox() { }
public
function
newInstance():*
{
var
combobox:ComboBox =
new
ComboBox();
combobox.dataProvider = customData;
combobox.editable =
true
;
combobox.setStyle(
"fontWeight"
,
"normal"
);
return
combobox;
}
}
}
|
然后给itemEditor一个实例:col.itemEditor = new CustomComboBox();
这样,文章开头的那个MXML写的DataGrid就全由AS生成了。完整代码:
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
mx:Application
xmlns:mx
=
"http://www.adobe.com/2006/mxml"
layout
=
"absolute"
initialize
=
"init()"
>
<
mx:Script
>
<![CDATA[
import mx.controls.dataGridClasses.DataGridColumn;
import mx.collections.ArrayCollection;
import mx.controls.DataGrid;
import mx.events.ListEvent;
import mx.controls.ComboBox;
[Bindable]
private var dgDataArr:Array = [{name: "Jon", job: "officer"},
{name: "James", job: "seller"},
{name: "Jodon", job: "manager"}];
private function init():void
{
var dgData:ArrayCollection = new ArrayCollection(dgDataArr);
dgData.filterFunction
var dataGrid:DataGrid = new DataGrid();
dataGrid.x = 10;
dataGrid.y = 20;
dataGrid.editable = true;
dataGrid.percentWidth = 100;
dataGrid.setStyle("fontSize", 14);
dataGrid.styleName
dataGrid.dataProvider = dgData;
dataGrid.addEventListener(ListEvent.ITEM_CLICK, itemClickHandler);
addChild(dataGrid);
var columns:Array = new Array();
var col:DataGridColumn;
for ( var i:* in dgDataArr[0] ) {
col = new DataGridColumn(i);
if ( i == "name" ) col.editable = false;
if ( i == "job" ) {
var comboboxFactory:ClassFactory = new ClassFactory(ComboBox);
comboboxFactory.properties = { dataProvider: ["officer", "seller", "manager"], editable: true };
col.itemEditor = comboboxFactory;
}
columns.push(col);
}
dataGrid.columns = columns;
}
private function itemClickHandler(e:ListEvent):void
{
trace(e.target);
}
]]>
</
mx:Script
>
</
mx:Application
>
|