Flex之旅--AdvancedDataGrid 修改树节点图标

        使用Flex AdvancedDataGrid可以在列表中展示树形结构,但默认的图标为文件夹及文件图标,如图。如果想修改图标,且只是简单替换默认图标可以使用如下方式:

		<mx:AdvancedDataGrid folderOpenIcon="@Embed('assets/images/open.jpg')" 
				folderClosedIcon="@Embed('assets/images/close.jpg')" 
				defaultLeafIcon="@Embed('assets/images/leaf.jpg')">

        

        但如果想根据数据不同,显示不同的图标会麻烦一些。如上图,要求不同部门显示不同图标,人员要根据职位显示不同图标。在测试过程中试过使用姓名列的itemRenderer,但这种方法只能改掉叶子节点的图标,非叶子节点的文件夹图标改不掉。后来试过直接使用AdvancedDataGrid的itemRenderer,但也没能实现想要的效果。最后还是从folderOpenIcon,folderClosedIcon,defaultLeafIcon入手,写一个类继承Image,根据数据不同赋不同的source值,代码如下:

package com.demo
{
	import flash.events.Event;
	import mx.controls.Alert;
	import mx.controls.Image;
	import mx.controls.advancedDataGridClasses.AdvancedDataGridGroupItemRenderer;
	import mx.formatters.DateFormatter;

	public class FolderAndLeafIcon extends Image
	{
		[Embed(source="assets/images/employee.jpg")]   
		private const employee:Class;
		
		[Embed(source="assets/images/manager.jpg")]   
		private const manager:Class;
		
		[Embed(source="assets/images/renli.jpg")]   
		private const renli:Class;
		
		[Embed(source="assets/images/yanfa.jpg")]   
		private const yanfa:Class;
		
		public function FolderAndLeafIcon()
		{
			super();
			this.addEventListener(Event.ADDED_TO_STAGE, setIconSource);
		}
		
		private function setIconSource(event:Event):void{
			var folderIcon:FolderAndLeafIcon = event.currentTarget as FolderAndLeafIcon;
			
			if(folderIcon){
				folderIcon.source = getIconSourceValue(folderIcon);
			}
		}
		
		public function getIconSourceValue(folderIcon:FolderAndLeafIcon):Class{
			var advancedGridGroupItemRender:AdvancedDataGridGroupItemRenderer = folderIcon.parent as AdvancedDataGridGroupItemRenderer;
			var source:Class;
			
			if(advancedGridGroupItemRender){
				
				// 当advancedGridGroupItemRender.data包含dept,name,manager等属性时,当前是叶子节点
				if (advancedGridGroupItemRender.data.hasOwnProperty("manager")) {
					
					var m:int = advancedGridGroupItemRender.data.manager;
					
					if (m == 1) {
						source = manager;
					}
					else if (m == 0) {
						source = employee;
					}
				}
				else {	// 非叶子节点
					var dept:String = advancedGridGroupItemRender.listData.label;
				
					if (dept == "人力") {
						source = renli;
					}
					else if (dept == "研发") {
						source = yanfa;
					}
				}
			}
			
			return source;
		}
	}
}
        上面代码获得advancedGridGroupItemRender是关键,还有就是怎样获得数据也是关键,advancedGridGroupItemRender.listData.label获得的是当前单元格的文本内容,advancedGridGroupItemRender.data获得的是当前行的数据。非叶子节点时advancedGridGroupItemRender.data得到的行数据是空的,只能通过advancedGridGroupItemRender.listData.label得到当前单元格文本内容。测试时在这个地方花费了很多时间,一直得不到data中的属性值。    

        下面看一下调用的代码(注意第一列不能设置visible="false",否则无法显示数据):

	<fx:Declarations>
		<mx:GroupingCollection id="gc" source="{dataSource}">  
			<mx:Grouping>  
				<mx:GroupingField name="dept"/>  
			</mx:Grouping>  
		</mx:GroupingCollection> 
	</fx:Declarations>
	
	<fx:Script>
		<![CDATA[
			import com.demo.FolderAndLeafIcon;
			
			import mx.collections.ArrayCollection;
			[Bindable]
			public var dataSource:ArrayCollection = new ArrayCollection([
				{dept:"人力", name:"张三", sex:0, age:25, telnumber:"123456", manager:1},
				{dept:"人力", name:"李四", sex:1, age:20, telnumber:"123456", manager:0},
				{dept:"研发", name:"王五", sex:1, age:21, telnumber:"123456", manager:1},
				{dept:"研发", name:"赵六", sex:0, age:22, telnumber:"123456", manager:0},
				{dept:"研发", name:"钱七", sex:1, age:23, telnumber:"123456", manager:0}
			]);
		]]>
	</fx:Script>
	
	<mx:AdvancedDataGrid dataProvider="{gc}" initialize="gc.refresh()" defaultLeafIcon="{FolderAndLeafIcon}"
						 folderOpenIcon="{FolderAndLeafIcon}" folderClosedIcon="{FolderAndLeafIcon}" >
		<mx:columns>
			<mx:AdvancedDataGridColumn headerText="姓名" dataField="name"  />
			<mx:AdvancedDataGridColumn headerText="性别" dataField="sex" itemRenderer="com.demo.SexRenderer"/>
			<mx:AdvancedDataGridColumn headerText="年龄" dataField="age" textAlign="center"/>
			<mx:AdvancedDataGridColumn headerText="电话" dataField="telnumber" textAlign="center"/>
		</mx:columns>
	</mx:AdvancedDataGrid>
        上面性别列定义了itemRenderer,显示图片,代码如下:

<s:MXAdvancedDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
								  xmlns:s="library://ns.adobe.com/flex/spark" 
								  xmlns:mx="library://ns.adobe.com/flex/mx" 
								  focusEnabled="true">
	
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			[Embed(source="assets/images/male.jpg")]   
			private const male:Class;	
			
			[Embed(source="assets/images/female.jpg")]   
			private const female:Class;	
			
			private function getIcon(sex:String):Class {
				
				if (sex == "1") {
					return male;
				}
				else if (sex == "0"){
					return female;
				}
				else {
					return null;
				}
			}
			
			private function getIcon1(data:Object):Class {
				
				if (data.sex == 1) {
					return male;
				}
				else if (data.sex == 0){
					return female;
				}
				else {
					return null;
				}
			}
		]]>
	</fx:Script>
	<s:layout>
		<s:HorizontalLayout verticalAlign="middle" horizontalAlign="center" />
	</s:layout>
	<mx:Image source="{getIcon(listData.label)}"/>
	<!--<mx:Image source="{getIcon1(data)}"/>-->
</s:MXAdvancedDataGridItemRenderer>
        上面代码使用两个方法获得图片,一个是通过data,一个是listData.label,还是前面说的,data是当前行数据,listData.label是当前单元格文本。最后效果如下图:



        追加简单方法:

        发现一简单方法,AdvancedDataGrid有个iconFunction属性,类型是function,自己定义一个function返回图标。现在可以删掉defaultLeafIcon,folderOpenIcon,folderClosedIcon,添加iconFunction="getIcon",执行效果和前面一样。

			private function getIcon(item:Object):Class {
				
				var source:Class;
				
				// 如果是非叶子节点,则item存在GroupLabel属性,值为节点文字内容
				if (item.GroupLabel == "人力") {
					source = renli;
				}
				else if (item.GroupLabel == "研发") {
					source = yanfa;
				}
				else {	// 叶子节点时item为当前行数据
					if (item.manager == 1) {
						source = manager;
					}
					else if (item.manager == 0) {
						source = employee;
					}
				}
				
				return source;
			}
下图为debug模式下,item对象数据内容:




©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页