相信每个开发过flex的用户都用过datagrid,但是传统的datagrid有很多弱点,例如有一个弱点就是比较难在内存动态生成头部的标题,如果您只是一个传入一个未知的二维表结构,希望它动态显示就让人感觉无能为力了,所以为力完善相关的设计,我尝试用xml动态定义了标题,如果大家喜欢这个代码请给我留个支持哦。
datagrid代码
<?xml version="1.0" encoding="utf-8"?><mx:DataGrid xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="datagrid_creationCompleteHandler(event)"> <!-- type="image/html/external" --> <fx:Declarations> <fx:XML id="titleXml" xmlns=""> <nodes> <node width="20"> <ename>key1</ename> <cname>key1</cname> </node> <node width="30%"> <ename>key2</ename> <cname>key2</cname> </node> </nodes> </fx:XML> <fx:XML id="xml" xmlns=""> <nodes> <node> <key1>value1</key1> <key2>value2</key2> </node> </nodes> </fx:XML> </fx:Declarations> <fx:Script> <!--[CDATA[ import com.shine.framework.DBUtil.model.DBModel; import com.shine.framework.core.model.BaseXmlModel; import com.shine.framework.core.model.XmlModel; import com.shine.framework.core.util.ArrayMap; import com.shine.framework.core.util.DataUtil; import mx.controls.Alert; import mx.controls.dataGridClasses.DataGridColumn; import mx.events.FlexEvent; import spark.components.TextArea; //是否允许下载文件 public var downloadPolicy:String="off"; //单元格类型 public var itemRendererClass:ClassFactory=null; //初始化 private function datagrid_creationCompleteHandler(event:FlexEvent):void { var titleArray:Array=new Array; if(titleXml!=null){ for each (var xml:XML in titleXml.children()) { var dataGridColumn:DataGridColumn=new DataGridColumn; dataGridColumn.dataField=XML(xml.ename).toString(); dataGridColumn.headerText=XML(xml.cname).toString(); if(xml.@width!=null&&String(xml.@width).length!=0){ if(String(xml.@width).indexOf("%")!=-1){ dataGridColumn.width=this.width*int(DataUtil.StringReplaceAll(String(xml.@width),"%","")); }else{ dataGridColumn.width=int(xml.@width); } } if(String(xml.@type)==null){ }else if(String(xml.@type)=="image"){ dataGridColumn.itemRenderer=new ClassFactory(com.shine.framework.core.view.ImageDataGridRender); }else if(String(xml.@type)=="html"){ dataGridColumn.itemRenderer=new ClassFactory(com.shine.framework.core.view.HTMLDataGridRender); }else if(String(xml.@type)=="external"){ if(itemRendererClass!=null) dataGridColumn.itemRenderer=itemRendererClass; } titleArray.push(dataGridColumn); dataGridColumn=null; } this.columns=titleArray; titleArray=null; } this.dataProvider=xml.children(); initRightContext(); } //加入DataGrid public function addModel(value:ArrayMap):void{ for(var i:int=0;i<value.getLength();i++){ if(value.get(i) is BaseXmlModel) addRowByModel(value.get(i) as BaseXmlModel); } } //通过model加入新的一行 public function addRowByModel(value:BaseXmlModel):void{ var dataXml:XML=this.xml.appendChild(XML(value.getBaseXmlValue())); this.dataProvider=dataXml.children(); } //直接把数值插入新的一行 public function addRowByValue(...arg):void{ var num:int=arg.length; var xmllist:XMLList=this.titleXml.children(); if(num==xmllist.length()){ var model:BaseXmlModel=new BaseXmlModel; for(var i:int=0;i<num;i++){ model.put(XML(XML(xmllist[i]).child("ename")).toString(),arg[i]); } addRowByModel(model); model=null; }else{ Alert.show("行数据不正确","提示"); } } //删除其中一行 public function removeDataGridRow(num:int):void{ var xmlModel:XmlModel=new XmlModel(this.xml); xmlModel.deleteXmlByIndex(num); this.xml=XML(xmlModel.getOriginalXmlValue()); } //清空数据单元 public function cleanDataGridRow():void{ this.xml=XML("<nodes />"); } //获取表格高度 public function getDataGridRowLenght():int{ return this.xml.children().length(); } //空白处右键 private function initRightContext():void { var contextMenu:ContextMenu=new ContextMenu(); contextMenu.hideBuiltInItems(); if (downloadPolicy == "on") { var saveExcelContextMenuItem:ContextMenuItem=new ContextMenuItem("导出为Excel"); saveExcelContextMenuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, saveExcel); contextMenu.customItems.push(saveExcelContextMenuItem); } this.contextMenu=contextMenu; } //导出Excel private function saveExcel(event:ContextMenuEvent):void { //loadDGInExcel(this, 'http://127.0.0.1:8080/SaleSystem/services/ExcelExport.jsp'); loadDGInExcelBySave(this); } ]]> </fx:Script> <fx:Script> <![CDATA[ /** * Simple script to convert a Datagrid to a HTML table and then * pass it on to an external excel exporter * */ //Libs that are mostly used //(only a number are necessary for the datagrid conversion and export) import flash.errors.*; import flash.events.*; import flash.external.*; import flash.net.URLRequest; import flash.net.URLVariables; /** * Convert the datagrid to a html table * Styling etc. can be done externally * * @param: dg Datagrid Contains the datagrid that needs to be converted * @returns: String */ private function convertDGToHTMLTable(dg:DataGrid):String { //Set default values var font:String=dg.getStyle('fontFamily'); var size:String=dg.getStyle('fontSize'); var str:String=''; var colors:String=''; var style:String='style="font-family:' + font + ';font-size:' + size + 'pt;"'; var hcolor:Array; //Retrieve the headercolor if (dg.getStyle("headerColor") != undefined) { hcolor=[dg.getStyle("headerColor")]; } else { hcolor=dg.getStyle("headerColors"); } //Set the htmltabel based upon knowlegde from the datagrid //flex3 //str+='<table width="' + dg.width + '" border="1"><thead><tr width="' + dg.width + '" style="background-color:#' + Number((hcolor[0])).toString(16) + '" mce_style="background-color:#' + Number((hcolor[0])).toString(16) + '">'; //flex4 str+='<table width="' + dg.width + '" border="1"><thead><tr width="' + dg.width + '" style="background-color:#' + 0xffffff.toString(16) + '" mce_style="background-color:#' + 0xffffff.toString(16) + '">'; //Set the tableheader data (retrieves information from the datagrid header for (var i:int=0; i < dg.columns.length; i++) { colors=dg.getStyle("themeColor"); if (dg.columns[i].headerText != undefined) { str+="<th " + style + ">" + dg.columns[i].headerText + "</th>"; } else { str+="<th " + style + ">" + dg.columns[i].dataField + "</th>"; } } str+="</tr></thead><tbody>"; colors=dg.getStyle("alternatingRowColors"); //Loop through the records in the dataprovider and //insert the column information into the table for (var j:int=0; j < dg.dataProvider.length; j++) { str+="<tr width=/"" + Math.ceil(dg.width) + "/">"; for (var k:int=0; k < dg.columns.length; k++) { //Do we still have a valid item? if (dg.dataProvider.getItemAt(j) != undefined && dg.dataProvider.getItemAt(j) != null) { //Check to see if the user specified a labelfunction which we must //use instead of the dataField if (dg.columns[k].labelFunction != undefined) { str+="<td width=/"" + Math.ceil(dg.columns[k].width) + "/" " + style + ">" + dg.columns[k].labelFunction(dg.dataProvider.getItemAt(j), dg.columns[k].dataField) + "</td>"; } else { //Our dataprovider contains the real data //We need the column information (dataField) //to specify which key to use. str+="<td width=/"" + Math.ceil(dg.columns[k].width) + "/" " + style + ">" + dg.dataProvider.getItemAt(j)[dg.columns[k].dataField] + "</td>"; } } } str+="</tr>"; } str+="</tbody></table>"; return str; } /** * Load a specific datagrid into Excel * This method passes the htmltable string to an backend script which then * offers the excel download to the user. * The reason for not using a copy to clipboard and then javascript to * insert it into Excel is that this mostly will fail because of the user * setup (Webbrowser configuration). * * @params: dg Datagrid The Datagrid that will be loaded into Excel * @params: url String The location of the excel export file */ private function loadDGInExcel(dg:DataGrid, url:String):void { //Pass the htmltable in a variable so that it can be delivered //to the backend script var variables:URLVariables=new URLVariables(); variables.htmltable=convertDGToHTMLTable(dg); //Setup a new request and make sure that we are //sending the data through a post var u:URLRequest=new URLRequest(url); u.data=variables; //Pass the variables u.method=URLRequestMethod.POST; //Don't forget that we need to send as POST //Navigate to the script //We can use _self here, since the script will through a filedownload header //which results in offering a download to the user (and still remaining in you Flex app.) navigateToURL(u, "_self"); } private function loadDGInExcelBySave(dg:DataGrid):void { var ba:ByteArray=new ByteArray; ba.writeUTF(convertDGToHTMLTable(dg)); var _fileRef:FileReference=new FileReference(); _fileRef.save(ba, "data.xls"); //保存到磁盘,会出现个系统保存对话框。 ba.clear(); } ]]--> </fx:Script></mx:DataGrid>
代码的
<fx:XML id="titleXml" xmlns=""> <nodes> <node width="20"> <ename>key1</ename> <cname>key1</cname> </node> <node width="30%"> <ename>key2</ename> <cname>key2</cname> </node> </nodes> </fx:XML>
定义的是title
代码的
<fx:XML id="xml" xmlns=""> <nodes> <node> <key1>value1</key1> <key2>value2</key2> </node> </nodes> </fx:XML>
定义的是内容
调用的application
<?xml version="1.0" encoding="utf-8"?><s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:local="*" creationComplete="{complete()}" xmlns:view="com.shine.framework.core.view.*"> <fx:Declarations> <fx:XML id="titleXml" xmlns=""> <nodes> <node> <ename>key1</ename> <cname>key1</cname> </node> <node> <ename>key2</ename> <cname>key2</cname> </node> </nodes> </fx:XML> <fx:XML id="dataXml" xmlns=""> <nodes> <node> <key1>value1</key1> <key2>value2</key2> </node> <node> <key1>value3</key1> <key2>value4</key2> </node> </nodes> </fx:XML> </fx:Declarations> <fx:Script> <!--[CDATA[ private function complete():void{ sunshineDataGrid.dataProvider=dataXml.node; } ]]--> </fx:Script> <view:SunshineDataGrid id="sunshineDataGrid" width="100%" height="100%" titleXml="{titleXml}" downloadPolicy="on" /></s:Application>
实际效果
当然也可以动态定义宽度,也可以动态控制显示图片还是html都可以,下一篇文章给大家介绍一下