`
蒙太奇
  • 浏览: 51626 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Flex在Tree控件上添加CheckBox

    博客分类:
  • flex
阅读更多
告示:本文为原创文章, 如果转载请注明出处!http://summerofthatyear-gmail-com.iteye.com/blog/326302
      网上遇到很多需要在Tree控件添加CheckBox等控件的问题, 本以为把Tree的itemRenderer设置成mx.controls.CheckBox 就可以完事了, 但是试了之后才发现没有这么简单 . . .
      今天看了Tree的源码, Tree在初始化的时候默认给自己设置itemRenderer属性. 此属性值也是Flex现成的:mx.controls.treeClasses.TreeItemRenderer.
      它内部分为三部分:1,icon也是就三角形的小图标. 2,disclosureIcon文件夹图标. 3,label显示的文字. 我只要在label前面加上一个CheckBox就行了.
       于是我写了一个类:TreeCheckBoxRenderer继承mx.controls.treeClasses.TreeItemRenderer源码如下:
package com.montage.controls.treeClasses
{
import flash.events.Event;

import mx.controls.CheckBox;
import mx.controls.treeClasses.TreeItemRenderer;
import mx.controls.treeClasses.TreeListData;

/**
 * 支持CheckBox的TreeItemRenderer
 * @author Montage
 */	
public class TreeCheckBoxRenderer extends TreeItemRenderer
{
	public function TreeCheckBoxRenderer()
	{
		super();
	}
	
	/**
	 * 表示CheckBox控件从data中所取数据的字段
	 */		
	private var _selectedField:String = "selected";
	
	protected var checkBox:CheckBox;
	
	/**
	 * 构建CheckBox
	 */		
	override protected function createChildren():void
	{
		super.createChildren();
		checkBox = new CheckBox();
		addChild( checkBox );
		checkBox.addEventListener(Event.CHANGE, changeHandler);
	}
	
	/**
	 * 点击checkbox时,更新dataProvider
	 * @param event
	 */		
	protected function changeHandler( event:Event ):void
	{
		if( data && data[_selectedField] != undefined )
		{
			data[_selectedField] = checkBox.selected;
		}
	} 
	
	/**
	 * 初始化控件时, 给checkbox赋值
	 */		
	override protected function commitProperties():void
	{
		super.commitProperties();
		trace(data[_selectedField])
		if( data && data[_selectedField] != undefined )
		{
			checkBox.selected = data[_selectedField];
		}
		else
		{
			checkBox.selected = false;
		}
	}
	
	/**
	 * 重置itemRenderer的宽度
	 */		
	override protected function measure():void
	{
		super.measure();
		measuredWidth += checkBox.getExplicitOrMeasuredWidth();
	}
	
	/**
	 * 重新排列位置, 将label后移
	 * @param unscaledWidth
	 * @param unscaledHeight
	 */		
	override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
	{
		super.updateDisplayList(unscaledWidth, unscaledHeight);
		var startx:Number = data ? TreeListData( listData ).indent : 0;
		
		if (disclosureIcon)
		{
			disclosureIcon.x = startx;

			startx = disclosureIcon.x + disclosureIcon.width;
			
			disclosureIcon.setActualSize(disclosureIcon.width,
										 disclosureIcon.height);
			
			disclosureIcon.visible = data ?
									 TreeListData( listData ).hasChildren :
									 false;
		}
		
		if (icon)
		{
			icon.x = startx;
			startx = icon.x + icon.measuredWidth;
			icon.setActualSize(icon.measuredWidth, icon.measuredHeight);
		}
		
		checkBox.move(startx, ( unscaledHeight - checkBox.height ) / 2 );
		
		label.x = startx + checkBox.getExplicitOrMeasuredWidth();
	}
}
}


测试文件如下:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" fontSize="12">
	<mx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;
			
			[Bindable]
			public var collection:ArrayCollection = new ArrayCollection([
				{ "name" : "上海", "selected":false, "children":[
					{ "name":"黄浦", "selected":false },
					{ "name":"浦东", "selected":true },
					{ "name":"静安", "selected":false },
					{ "name":"徐汇", "selected":false }
				]},
				{ "name":"北京", "selected":false, "children":[
					{ "name":"海淀", "selected":false },
					{ "name":"朝阳", "selected":true },
					{ "name":"丰台", "selected":false }
				]}
			]);
			
		]]>
	</mx:Script>
	<mx:Tree width="300" height="500" labelField="name" 
itemRenderer="com.montage.controls.treeClasses.TreeCheckBoxRenderer" dataProvider="{collection}"/>
</mx:Application>


      注意:selected属性很重要, 此属性在数据源内, 标致当前节点的CheckBox是否选中.点击CheckBox会自动改变响应的数据源.  如果想知道哪些被选中的话, 就遍历Tree的dataProvider吧~
      谨以此文贡献给战斗在RIA第一线的兄弟姐妹们.
  • 大小: 11.6 KB
分享到:
评论
10 楼 蒙太奇 2009-09-25  
reanfan 写道
蒙太奇 写道
avanry 写道
我新手,没看太懂
如果我想实现选择第一层的时候,它下面的子层都选中
就像上海,点击之后,下面的几个区都选中,可以做到吗?

这个暂时要你自己判断了 监听选中的项 然后通过修改数据源来实现子级的选中。


我也是新手 请问如何在外部监听选中的项呢 请楼主详告之

这个控件目前还不支持,没有事件发出来。
你可以在changeHandler()方法里面,派发一个事件,相应的参数随事件传递出去。在外部侦听这个事件,再根据参数做相应的修改。
9 楼 reanfan 2009-09-23  
蒙太奇 写道
avanry 写道
我新手,没看太懂
如果我想实现选择第一层的时候,它下面的子层都选中
就像上海,点击之后,下面的几个区都选中,可以做到吗?

这个暂时要你自己判断了 监听选中的项 然后通过修改数据源来实现子级的选中。


我也是新手 请问如何在外部监听选中的项呢 请楼主详告之
8 楼 蒙太奇 2009-07-23  
avanry 写道
我新手,没看太懂
如果我想实现选择第一层的时候,它下面的子层都选中
就像上海,点击之后,下面的几个区都选中,可以做到吗?

这个暂时要你自己判断了 监听选中的项 然后通过修改数据源来实现子级的选中。
7 楼 avanry 2009-07-21  
我新手,没看太懂
如果我想实现选择第一层的时候,它下面的子层都选中
就像上海,点击之后,下面的几个区都选中,可以做到吗?
6 楼 蒙太奇 2009-07-21  
chxkyy 写道
在createChildren里。我只要对叶子节点添加checkbox。
我的叶子节点数据如下所示:
<treeNode type="leaf" title="华东电力企业" url="..."/>


有什么解决办法吗?


这个itemRenderer里面
private var _selectedField:String = "selected";  
默认是到当前数据节点上找selected属性,如果你用
<treeNode type="leaf" title="华东电力企业" url="..."/> 
这个数据格式的话,用要在xml里面加一个 selected="true"
<treeNode type="leaf" title="华东电力企业" url="..." selected="true"/> 
对应的itemRenderer里面的_selectedField = "@selected".
5 楼 chxkyy 2009-07-07  
在createChildren里。我只要对叶子节点添加checkbox。
我的叶子节点数据如下所示:
<treeNode type="leaf" title="华东电力企业" url="..."/>


有什么解决办法吗?
4 楼 蒙太奇 2009-03-09  
stxu1987 写道
搞错了 原来是 data[_selectedField] 这种访问属性的方式不行 用@来访问属性就可以了 thank you all the same

对itemRenderer的控件不是很方便, 你用的xml数据源,访问发生要加@.我这里默认是"selected",所以.
3 楼 stxu1987 2009-03-09  
搞错了 原来是 data[_selectedField] 这种访问属性的方式不行 用@来访问属性就可以了 thank you all the same
2 楼 蒙太奇 2009-03-07  
stxu1987 写道

protected function changeHandler( event:Event ):void&nbsp;
&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( data &amp;&amp; data[_selectedField] != undefined )&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data[_selectedField] = checkBox.selected;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;
这里的data 始终都是undefined&nbsp; 。 因此 , 没有将值写入 dataprovider。
如何解决?

如果你给Tree设置过dataProvider,data就不应该是undefined了.
1 楼 stxu1987 2009-03-06  
protected function changeHandler( event:Event ):void 
    {  
        if( data && data[_selectedField] != undefined )  
        {  
            data[_selectedField] = checkBox.selected;  
        }  
    }   
这里的data 始终都是undefined  。 因此 , 没有将值写入 dataprovider。
如何解决?

相关推荐

Global site tag (gtag.js) - Google Analytics