Flex DataGrid组件
实际上,DataGrid组件是属于列表组件的,之所以单独拿出来讲解,主要是因为 DataGrid组件有着很强大的功能,也有很多扩展的应用是在开发中经常用到的。DataGrid组件是按照行和列的形式显示数据的。有几个类是只有 DataGrid组件才能使用的,包括DataGridCellEditor类、DataGridColumn类和HeaderRenderer类。这三 个类会在使用的时候逐个讲解。
15.1 数据网格(DataGrid)组件简介
DataGrid组件适合显示包含多个属性的对象。可以通过内部或者外部的数据源把数 据绑定到DataGrid组件中。DataGrid组件有很多强大的功能,使我们在开发中很容易地实现某些代码,比如,按照特定的规则排序,在单元格中嵌 入其他组件等。DataGrid组件有很多属性、方法和事件。常用的属性如表15.1所示,常用的方法如表15.2所示。
表15.1 DataGrid组件常用的属性
属 性 |
说 明 |
columns |
获取或设置一个DataGridColumn对象数组,每个可以显示的列为一个对象 |
editable |
指示用户能否编辑数据提供者中的项目 |
editedItemPosition |
获取或设置正在编辑的数据提供者项目的项目渲染器的列索引和行索引 |
editedItemRenderer |
获取对当前正在编辑的项目所属的DataGrid组件中项目渲染器的引用 |
headerHeight |
获取或设置DataGrid标题的高度,以像素为单位 |
horizontalScrollPolicy |
获取或设置一个布尔值,指示水平滚动条是否始终打开 |
imeMode |
获取或设置输入法编辑器(IME)的模式 |
itemEditorInstance |
对项目编辑器的当前活动实例(如果有)的引用 |
labelFunction |
获取或设置一个函数,确定各个项目的哪些字段要用作标签文本 |
minColumnWidth |
获取或设置DataGrid组件列的最小宽度,以像素为单位 |
resizableColumns |
指示用户能否更改列的尺寸 |
rowCount |
获取或设置在列表中至少部分可见的行的行数 |
rowHeight |
获取或设置DataGrid组件中每一行的高度以像素为单位 |
showHeaders |
获取或设置一个布尔值,该值指示DataGrid组件是否显示列标题 |
sortableColumns |
指示用户能否通过单击列标题单元格对数据提供者中的项目进行排序 |
sortDescending |
获取当用户单击列标题时列的排序顺序 |
sortIndex |
获取要排序的列的索引 |
表15.2 DataGrid组件常用的方法
方 法 |
说 明 |
addColumn |
在columns数组的末尾添加列 |
addColumnAt |
在column数组中的指定索引处插入列 |
createItemEditor |
使用itemEditor属性指定的编辑器为位于editedItemPosition属性标识的列索引和行索引处的项目渲染器创建项目编辑器 |
destroyItemEditor |
关闭当前在项目渲染器上打开的项目编辑器 |
editField |
编辑DataGrid组件中的给定字段或属性 |
getCellRendererAt |
获取DataGrid中指定位置的单元格渲染器的实例 |
getColumnAt |
检索位于columns数组中指定索引处的列 |
getColumnCount |
检索DataGrid组件中的列数 |
getColumnIndex |
检索具有指定名称的列的索引;如果未找到匹配项,则为 -1 |
getStyleDefinition |
检索当前组件的默认样式映射 |
itemToCellRenderer |
DataGrid组件对任何给定项都有多个单元格,因此itemToCellRenderer方法始终返回null |
removeAllColumns |
删除DataGrid组件中的所有列 |
removeColumnAt |
删除位于columns数组中指定索引处的列 |
scrollToIndex |
将列表滚动至位于指定索引处的项目 |
spaceColumnsEqually |
将可见列的宽度重置为相同大小 |
可以利用这些属性、方法和事件创建强大的DataGrid组件应用程序。在接下来的几节,会逐一介绍他们的使用方法。
15.2 使用DataGrid组件显示数据列表
显示数据列表是DataGrid组件最基本的应用,只有把数据显示出来,才可以实现其 他的功能。数据的来源大概有两种,一种是内部数据,即在程序内部自定义数据,然后绑定到DataGrid组件中;另一种是外部数据,通过读取外部文件或者 是数据库,绑定到DataGrid组件中。接下来,就这两种情况分别做介绍。
15.2.1 将内部数据绑定到DataGrid组件中
要在DataGrid组件中显示数据,首先就要建立数据源,建立数据源通常是通过DataProvider API类来实现。下面的示例说明如何在DataGrid组件中显示数据,示例的步骤如下所示。
创建一个ActionScript 3.0文件,命名为DataGrid_ShowData_Example.as,类名为DataGrid_ShowData_Example,导入将用到的类库,代码如下所示:
package
{
import fl.controls.DataGrid;
import fl.controls.ScrollPolicy;
import fl.data.DataProvider;
import flash.display.Sprite;
public class DataGrid_ShowData_Example extends Sprite
{
/*****************************************
* 构造函数
* */
public function DataGrid_ShowData_Example()
{
}
}
}
创建一个函数GetData1,在内部实现具体的功能。代码如下所示:
/*********************************
* 加载内部数据,绑定DataGrid组件
* */
private function GetData1():void
{
}
在函数的内部,利用DataProvider类创建一个数据模型,这个数据模型有4列及10行数据,代码如下所示:
// 数据模型
var dp1:DataProvider = new DataProvider();
dp1.addItem({Name:"Tom", Phone:23579086, QQ:77788899, Software:"Flash"});
dp1.addItem({Name:"Kelly", Phone:33579080, QQ:56788823, Software:"Flex"});
dp1.addItem({Name:"Jim", Phone:83579085, QQ:56788882, Software:"Java"});
dp1.addItem({Name:"Sam",Phone:73579084,QQ:78988811,Software:"Dreamweaver"});
dp1.addItem({Name:"Kaiven",Phone:33576681,QQ:32188897,Software:"Photoshop"});
dp1.addItem({Name:"Gray", Phone:23229086, QQ:12388900, Software:"Fireworks"});
dp1.addItem({Name:"Luar", Phone:23579087, QQ:24681899, Software:"DAEMON Tools"});
dp1.addItem({Name:"Kite", Phone:85579082, QQ:68080894, Software:"FlashDevelop"});
dp1.addItem({Name:"Polar", Phone:32579086, QQ:21586899, Software:"Beyond Compare"});
初始化DataGrid组件,并实例化,然后设置属性,包括位置、宽度、高度、滚动条的样式等。代码如下所示:
// 初始化DataGrid组件,并实例化
var dg1:DataGrid = new DataGrid();
// 设置位置
dg1.move(20,20);
// 设置宽和高
dg1.setSize(350, 150);
dg1.verticalScrollPolicy = ScrollPolicy.AUTO;
定义列的标题,然后把数据模型和DataGrid组件绑定在一起,放到舞台上,代码如下所示:
// 定义列的标题
dg1.columns = ["Name", "Phone", "QQ", "Software"];
// 绑定数据源
dg1.dataProvider = dp1;
addChild(dg1);
编译代码并运行,效果如图15.1所示。
图15.1 读取内部数据,在DataGrid中显示
15.2.2 将外部数据绑定到DataGrid组件中
外部数据通常指的是数据库、文本本件和XML文件。在实际开发中,与数据层传入数据大多是通过XML格式传输的。所以,下面就创建一个读取外部XML文件的数据,然后在DataGrid组件中显示的例子。步骤如下。
创建一个XML文件,命名为DataGrid_Data.xml,内容结构如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<node label="Flash">
<Name>Flash</Name>
<Company>Adobe</Company>
<Version>9.0</Version>
</node>
<node label="Java">
<Name>Java</Name>
<Company>Sun</Company>
<Version>6.0</Version>
</node>
<node label=".Net">
<Name>.Net</Name>
<Company>Microsoft</Company>
<Version>2.0</Version>
</node>
<node label="Flex">
<Name>Flex</Name>
<Company>Adobe</Company>
<Version>2.0</Version>
</node>
<node label="OICQ">
<Name>OICQ</Name>
<Company>腾讯</Company>
<Version>2007</Version>
</node>
</root>
继续使用15.2.1节的文件,在DataGrid_ShowData_Example.as文件中,创建一个名为GetData2的函数,在函数中读取刚才创建的XML文件,代码如下所示:
/*********************************
* 加载外部XML数据
* */
private function GetData2():void
{
// 加载外部XML文件
data_xml = new XML();
myXMLURL = new URLRequest("DataGrid_Data.xml");
myLoader = new URLLoader(myXMLURL);
}
在类的外部,引入刚才使用的命名空间,包括URLRequest和URLLoader,代码如下:
import flash.net.URLRequest;
import flash.net.URLLoader;
创建上面的全局变量,data_xml、myXMLURL和myLoader。代码如下所示:
private var data_xml:XML;
private var myXMLURL:URLRequest;
private var myLoader:URLLoader;
创建XML对象的加载文件事件,并且在GetData2函数中添加侦听事件的语句,添加的侦听语句代码如下:
myLoader.addEventListener("complete", xmlLoaded);
XML对象的加载文件事件函数代码如下:
/*********************************
* 绑定DataGrid组件
* */
function xmlLoaded(event:Event):void
{
data_xml = XML(myLoader.data);
//trace(data_xml.elements("node").toXMLString());
}
在侦听事件函数中,把从外部读取的数据文件绑定到DataGrid组件中,代码如下:
// DataProvider
var dp:DataProvider = new DataProvider(data_xml);
// 初始化DataGrid组件,并实例化
var dg2:DataGrid = new DataGrid();
// 设置宽和高
dg2.setSize(200, 300);
// 定义列的标题
dg2.columns = ["Name", "Company", "Version"];
// 绑定数据源
dg2.dataProvider = dp;
addChild(dg2);
最后,在构造函数中,调用GetData2函数,代码如下:
/*****************************************
* 构造函数
* */
public function DataGrid_ShowData_Example()
{
GetData2();
}
编译代码并运行,效果如图15.2所示。
图15.2 读取外部数据绑定DataGrid组件
15.3 定义DataGrid组件样式外观
在实际程序开发中,有时候需要对DataGrid组件可视化的外观进行修改,以满足功能需要。例如,修改数据显示格式、修改DataGrid的样式和外观、自定义单元格等。
15.3.1 修改数据显示格式
当DataGrid组件显示出数据后,有些数据格式可能不是我们所需要的。这个时候,就要修改数据格式,把数据修改成有意义的,可以使读者更容易读懂的格式。比如货币格式前面要加美元符号或者人民币符号,有时候从数据库中读出的是0或1的布尔值,再比如电话号码等。
下面就以15.2.1节的实例为例,把Phone列修改成前面有区号的电话号码,步骤如下。
修改GetData1函数,在绑定数据源的语句之后,增加格式化语句,增加的代码如下所示:
// 格式化数据
dg1.getColumnAt(1).labelFunction = phoneFormatter;
phoneFormatter是格式化数据的函数,把电话号码前面加上区号“0755”,代码如下所示:
/*********************************
* 格式化电话号码
* */
private function phoneFormatter(item:Object):String
{
return "0755-" + item.Phone;
}
再次编译代码并运行,效果如图15.3所示。
图15.3 格式化电话号码
15.3.2 自定义DataGrid组件的标题
在显示完DataGrid组件的数据之后,有时候列的标题是数据库中已经定义好的列名 称,对于用户来说,不容易读懂,需要重新定义,那就需要自定义DataGrid组件的标题了。自定义标题要用到的类是 HeaderRenderer,HeaderRenderer类在类dataGridClasses中。下面就利用HeaderRenderer类来实现 自定义标题的功能。
还是以15.2.1节的实例为基础,加一些代码。在GetData1函数中加入如下代码:
// 自定义标题
var dgc0:DataGridColumn = dg1.getColumnAt(0);
dgc0.headerText = "姓名";
var dgc1:DataGridColumn = dg1.getColumnAt(1);
dgc1.headerText = "电话";
var dgc3:DataGridColumn = dg1.getColumnAt(3);
dgc3.headerText = "软件名称";
代码的作用是把第一行的标题改成“姓名”,第二行的标题改为“电话”,第三行的标题改为“软件名称”。再次编译运行,最终效果如图15.4所示。
图15.4 自定义DataGrid组件标题
15.4 DataGrid组件的分页与排序
当DataGrid组件中的数据显示很多行的时候,使用者需要不停地下拉滚动条。这对 于用户的体验极为不便,分页显示数据的方式就可以很好地解决这个问题。在应用软件开发中,分页也是常用的操作。排序的作用是为了用户可以更好地按照自己的 方式排列数据,更加方便地阅读数据信息。
15.4.1 DataGrid组件的分页
在很多语言中,分页技术都是很常见的。每种技术都有自己的优势和特点,但是基本思路都 差不多。基本思路是,把全部数据一次性读到一个数据集中,然后,再与DataGrid组件关联,分页的读取显示。另外一种思路是,先从数据库中读取一页的 数据,在DataGrid组件中显示出来,然后再读取,再显示。
下面,用第一种思路设计一个分页的程序,数据集采用数组的形式,利用数组的slice()方法,读取一部分数据,然后分页显示。步骤如下。
创建一个ActionScript 3.0文件,命名为DataGridPageExample,类名为DataGridPage- Example,继承自Sprite类,导入用到的类库。代码如下:
package
{
import fl.controls.Button;
import fl.controls.DataGrid;
import fl.controls.ScrollPolicy;
import fl.data.DataProvider;
import flash.display.Sprite;
import flash.events.MouseEvent;
public class DataGridPageExample extends Sprite
{
}
}
创建构造函数。代码如下所示:
/************************
* 构造函数
* **********************/
public function DataGridPageExample()
{
CreateDataModel();
CreateDataGrid();
CreatePageButton();
}
创建数据模型。实际开发中,是从外部数据库或者文件读取数据的,这里只是模拟数据源,便于讲解。在这里,插入了9条数据,然后传递到数组中,代码如下所示:
private var dp:DataProvider;
private var array:Array;
/************************
* 创建数据模型
* **********************/
private function CreateDataModel():void
{
// 数据模型
dp = new DataProvider();
// 插入9条数据
dp.addItem({Name:"Tom", Phone:23579086, QQ:77788899, Software:"Flash"});
dp.addItem({Name:"Kelly", Phone:33579080, QQ:56788823, Software:"Flex"});
dp.addItem({Name:"Jim", Phone:83579085, QQ:56788882, Software:"Java"});
dp.addItem({Name:"Sam", Phone:73579084, QQ:78988811, Software:"Dreamweaver"});
dp.addItem({Name:"Kaiven", Phone:33576681, QQ:32188897, Software:"Photoshop"});
dp.addItem({Name:"Gray", Phone:23229086, QQ:12388900, Software:"Fireworks"});
dp.addItem({Name:"Luar",Phone:23579087,QQ:24681899, Software:"DAEMON Tools"});
dp.addItem({Name:"Kite", Phone:85579082, QQ:68080894, Software:"FlashDevelop"});
dp.addItem({Name:"Polar",Phone:32579086,QQ:21586899,Software:"BeyondCompare"});
array = dp.toArray();
}
创建DataGrid组件,封装在函数CreateDataGrid中,代码如下所示:
private var dg:DataGrid;
// 数据副本
private var array_page:Array;
/************************
* 创建DataGrid组件
* **********************/
private function CreateDataGrid():void
{
// 初始化DataGrid组件,并实例化
dg = new DataGrid();
// 设置位置
dg.move(20,20);
// 设置宽和高
dg.setSize(350, 125);
dg.verticalScrollPolicy = ScrollPolicy.AUTO;
// 定义列的标题
dg.columns = ["Name", "Phone", "QQ", "Software"];
// 初始化数据
array_page = array.slice(0, 5);
// 绑定DataGrid组件
BingDataGrid(array_page);
addChild(dg);
}
绑定数据源,先是移除DataGrid组件中的所有数据,然后遍历参数数组中的数据,增加到DataGrid组件中。最后封装在函数BingDataGrid中,便于分页时重复调用。代码如下所示:
/************************
* 绑定数据源
* **********************/
private function BingDataGrid(array:Array):void
{
// 绑定数据源
dg.removeAll();
var i:uint = 0;
for(i=0; i<array.length; i++)
{
dg.addItem(array[i]);
}
}
创建“上一页”和”下一页“按钮,封装在函数CreatePageButton中,代码如下:
/************************
* 创建“上一页”和”下一页“按钮
* **********************/
private function CreatePageButton():void
{
var btnPre:Button = new Button();
var btnNext:Button = new Button();
btnPre.move(30, 170);
btnNext.move(240, 170);
btnPre.label = "上一页";
btnNext.label = "下一页";
btnPre.addEventListener(MouseEvent.CLICK, btnPreClick);
btnNext.addEventListener(MouseEvent.CLICK, btnNextClick);
addChild(btnPre);
addChild(btnNext);
}
创建“上一页”按钮的单击事件的函数,读取前5条数据,命名为btnPreClick,代码如下:
/************************
* “上一页”按钮的单击事件
* **********************/
public function btnPreClick(e:MouseEvent)
{
array_page = array.slice(0, 5);
BingDataGrid(array_page);
}
创建“下一页”按钮的单击事件的函数,读取后面的4条数据,命名为btnNextClick,代码如下:
/************************
* “下一页”按钮的单击事件
* **********************/
public function btnNextClick(e:MouseEvent)
{
array_page = array.slice(5, 10);
BingDataGrid(array_page);
}
把三个创建组件的函数增加到构造函数中,代码如下所示:
/************************
* 构造函数
* **********************/
public function DataGridPageExample()
{
CreateDataModel();
CreateDataGrid();
CreatePageButton();
}
最后编译运行,效果如图15.5所示。
图15.5 DataGrid组件分页
15.2 自定义DataGrid组件的单元格
DataGrid组件显示完数据之后,有些数据是需要用户自己定义或者修改的。这个时候就需要把需要用户修改的单元格变成可编辑的,以便于用户自己编辑。
15.5.1 编辑DataGrid组件的单元格
本节主要介绍如何定义一个单元格的编辑状态,下面的例子跟15.2.1节的例子差不多,但不同的是,应用了DataGridColumn类定义每个列的基本属性,然后再添加到DataGrid组件中。具体步骤如下。
创建一个ActionScript 3.0文件,命名为DataGridCellEditorExample,类名为DataGridCellEditorExample,继承自Sprite类,并导入用到的类库。代码如下所示:
package
{
import fl.controls.DataGrid;
import fl.controls.dataGridClasses.DataGridCellEditor;
import fl.controls.TextInput;
import fl.data.DataProvider;
import flash.display.Sprite;
import flash.text.TextFormat;
import fl.controls.dataGridClasses.DataGridColumn;
import fl.controls.ComboBox;
public class DataGridCellEditorExample extends Sprite
{
}
}
创建构造函数。代码如下所示:
/************************
* 构造函数
* **********************/
public function DataGridCellEditorExample()
{
}
创建DataGrid组件,封装在函数CreateDataGrid中。首先在函数中创建数据模型,代码如下所示:
/************************
* 创建DataGrid组件
* **********************/
private function CreateDataGrid():void
{
dg = new DataGrid();
// 设置大小
dg.setSize(350,300);
// 设置单元格的编辑状态
dg.editable = true;
// 创建数据模型
var dp:DataProvider = new DataProvider();
dp.addItem({Name:"Tom",Sex:"male",Phone:23579086,QQ:77788899,Software:"Flash"});
dp.addItem({Name:"Kelly",Sex:"female",Phone:33579080,QQ:56788823,Software:"Flex"});
dp.addItem({Name:"Jim",Sex:"male",Phone:83579085,QQ:56788882,Software:"Java"});
dp.addItem({Name:"Sam",Sex:"male",Phone:73579084,QQ:78988811,Software:"Dreamweaver"});
dp.addItem({Name:"Kaiven",Sex:"male",Phone:33576681,QQ:32188897,Software:"Photoshop"});
dp.addItem({Name:"Gray",Sex:"male",Phone:23229086,QQ:12388900,Software:"Fireworks"});
dp.addItem({Name:"Luar",Sex:"male",Phone:23579087,QQ:24681899,Software:"DAEMON Tools"});
dp.addItem({Name:"Kite",Sex:"female",Phone:85579082,QQ:68080894,Software:"FlashDevelop"});
dp.addItem({Name:"Polar",Sex:"male",Phone:32579086,QQ:21586899,Software:"Beyond Compare"});
在函数中,定义每个列,将性别和电话列的单元格设置成可编辑状态,添加的代码如下所示:
// 增加列,定义每个列的属性
var cellEditor:DataGridCellEditor = GetCustomEditor();
var sexcellEditor:DataGridCellEditor = GetCustomEditor_List();
// 增加定义“名字”列
var dgc_name:DataGridColumn = new DataGridColumn();
dgc_name.editable = false;
dgc_name.dataField = "Name";
//dgc_name.itemEditor = CellEditor;
dgc_name.sortable = true;
dg.addColumn(dgc_name);
// 增加定义“性别”列
var dgc_sex:DataGridColumn = new DataGridColumn();
dgc_sex.editable = true;
/dgc_sex.itemEditor = sexcellEditor;
dgc_sex.dataField = "Sex";
dgc_sex.sortable = true;
dgc_sex.width = 90;
dg.addColumn(dgc_sex);
// 增加定义“电话”列
var dgc_phone:DataGridColumn = new DataGridColumn();
dgc_phone.editable = true;
dgc_phone.dataField = "Phone";
dgc_phone.itemEditor = cellEditor;
dgc_phone.sortable = true;
dg.addColumn(dgc_phone);
// 增加定义“QQ”列
var dgc_qq:DataGridColumn = new DataGridColumn();
dgc_qq.editable = false;
dgc_qq.dataField = "QQ";
dgc_qq.sortable = true;
dg.addColumn(dgc_qq);
// 增加定义“软件”列
var dgc_soft:DataGridColumn = new DataGridColumn();
dgc_soft.editable = false;
dgc_soft.dataField = "Software";
dgc_soft.sortable = true;
dg.addColumn(dgc_soft);
dg.dataProvider = dp;
把DataGrid组件添加到舞台中,代码如下所示:
addChild(dg);
使用DataGridCellEditor对象,定义DataGrid组件单元格的样式,代码如下所示:
/************************
* 定义单元格样式
* **********************/
private function GetCustomEditor():DataGridCellEditor
{
var dgce:DataGridCellEditor = new DataGridCellEditor();
dgce.textField.background = true;
dgce.textField.backgroundColor = 0xCC99FF;
dgce.maxChars = 2;
dgce.restrict = "1234567890";
return dgce;
}
编译代码并运行,效果如图15.6所示。