Flex中DataGrid实现列(包括头部)中加入CheckBox全选功能 几种实现方法

时间:2022-05-03 09:20:22


在DataGrid中实现列中加入CheckBox这种用法很常见,项目中也经常会用到,在网上搜了下基本就是实现itemRender.但是 感觉网上提供的实现上好些地方都是多余的 经过自己的改造感觉还行 附上代码,同时希望大家举一反三 能实现添加其他组件到DataGrid列中

第一种方法:编写两个项选择器,继承CheckBox的方法,在DataGridview控件中的DataGridColumn列的属性headerRenderer,itemRenderer写入项选择器

CheckBoxHeaderRenderer.as

<pre class="java" name="code">package 
{
	
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	import mx.controls.CheckBox;
	import mx.controls.DataGrid;
	import mx.events.DataGridEvent;

	public class CheckBoxHeaderRenderer extends CheckBox
	{
		private var sele:String;
		public function CheckBoxHeaderRenderer()
		{
			super();
			this.addEventListener(Event.CHANGE, clickHandlers);
		}

		override public function set data(value:Object):void
		{
			DataGrid(listData.owner).addEventListener
                                    (DataGridEvent.HEADER_RELEASE,sortEventHandler);
			this.selected=this.sele=="true"?true:false;
		}
	
		private function sortEventHandler(event:DataGridEvent):void
		{
			if (event.itemRenderer == this)
				event.preventDefault();
		}
		
		protected function clickHandlers(event:Event):void
		{
			sele=(event.currentTarget.selected).toString();
			var a:ArrayCollection=DataGrid(listData.owner).dataProvider as ArrayCollection;
			for(var i:int=0;i<a.length;i++){

				(DataGrid(listData.owner).dataProvider as ArrayCollection)
                                   .getItemAt(i).selected=(event.currentTarget.selected).toString();
			}
			(DataGrid(listData.owner).dataProvider as ArrayCollection).refresh();
		}
	
	}
}  

 

CheckBoxItemDataRenderer.as

package 
{
	import flash.events.Event;	
	import mx.collections.ArrayCollection;
	import mx.controls.CheckBox;
	import mx.controls.DataGrid;

	public class CheckBoxItemDataRenderer extends CheckBox
	{
		private var currentData:Object; //保存当前一行值的对象
		public function CheckBoxItemDataRenderer()
		{
			super();		
			this.addEventListener(Event.CHANGE, changeHandler);
		}
		override public function set data(value:Object):void
		{
			this.currentData= value;
			this.selected = value.selected == "true"?true:false;
		}
		
		protected function changeHandler(event : Event) : void
		{
			currentData.selected = this.selected.toString();
		}
		/*override public function get data():Object{
			return currentData;
		}*/
	}
}

DataGrid_Checkbox.mxml

<?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"
			   xmlns:dataGrid="*"
			   minWidth="955" minHeight="600" creationComplete="getaa()">
	<fx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;
			import mx.controls.Alert;
			[Bindable]
			private var data_myDataGrid:ArrayCollection=new ArrayCollection();
			
			private function headerClickHandler(event : Event) : void
			{
			/* 	
				for each(var obj: Object in data_myDataGrid)
				{
					obj.selected = String(event.currentTarget.selected);
				}
				data_myDataGrid.refresh(); */
			}
			private function getaa():void{
				var obj:Object=new Object();
				obj.labe="1";
				obj.data="a";
				obj.selected="false";
				var obj2:Object=new Object();
				obj2.labe="2";
				obj2.data="b";
				obj2.selected="false";
				var obj3:Object=new Object();
				obj3.labe="3";
				obj3.data="c";
				obj3.selected="false";
				var obj4:Object=new Object();
				obj4.labe="4";
				obj4.data="a";
				obj4.selected="false";
				var obj5:Object=new Object();
				obj5.labe="5";
				obj5.data="b";
				obj5.selected="false";
				var obj6:Object=new Object();
				obj6.labe="6";
				obj6.data="c";
				obj6.selected="false";
				var obj7:Object=new Object();
				obj7.labe="7";
				obj7.data="a";
				obj7.selected="false";
				var obj8:Object=new Object();
				obj8.labe="8";
				obj8.data="b";
				obj8.selected="false";
				var obj9:Object=new Object();
				obj9.labe="9";
				obj9.data="c";
				obj9.selected="false";
				data_myDataGrid.addItem(obj);
				data_myDataGrid.addItem(obj3);
				data_myDataGrid.addItem(obj2);
				data_myDataGrid.addItem(obj4);
				data_myDataGrid.addItem(obj5);
				data_myDataGrid.addItem(obj6);
				data_myDataGrid.addItem(obj7);
				data_myDataGrid.addItem(obj8);
				data_myDataGrid.addItem(obj9);
			}

			protected function button1_clickHandler(event:MouseEvent):void
			{
				for(var i:int=0;i<data_myDataGrid.length;i++){
					if(data_myDataGrid.getItemAt(i).selected=='true'){
						Alert.show(data_myDataGrid.getItemAt(i).labe);
					}
				}
			}

		]]>
	</fx:Script>
	
	<mx:DataGrid dataProvider="{data_myDataGrid}" x="10" y="10">
		<mx:columns>
			<mx:DataGridColumn dataField="labe" headerText="Label" />
			<mx:DataGridColumn dataField="data" headerText="Data" />
			<mx:DataGridColumn
				dataField="selected" headerText="Select" 
				itemRenderer="CheckBoxItemDataRenderer" 
				headerRenderer="CheckBoxHeaderRenderer"  />
		</mx:columns>
	</mx:DataGrid>
	 <mx:Button click="button1_clickHandler(event)"/>
</s:Application>



第二种方法: 不继承checkBox类,直接在DataGrid中的DataGridColumn列中编写属性,项选择器,并写点击事件


用于存放数据的类,值得注意的是,selected属性用来存放复选框的状态.其他的是业务数据

package
{
	[Bindable]//此类必须是可绑定的//用于存放数据
	public class DataObject
	{
		public var index:Number;
		public var selected:Boolean = false;//<span style="font-family: Helvetica, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">存放复选框的状态</span>
		public var phone:String;
		public var name:String;
	}
}

应用程序

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
				layout="absolute"
				xmlns:ns1 ="com.common.*" creationComplete="application1_creationCompleteHandler(event)">
	<mx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;
			import mx.controls.Alert;
			import mx.core.UIComponent;
			import mx.events.DragEvent;
			import mx.events.FlexEvent;
			import mx.events.ListEvent;
			[Bindable]
			public var obj:ArrayCollection;//用于存放datagrid中的所有数据,以及所有复选框的状态
			[Bindable]
			public var nums:String="";
			
			
			protected function application1_creationCompleteHandler(event:FlexEvent):void
			{
				// TODO Auto-generated method stub
				var arr:ArrayCollection = new ArrayCollection();
				for(var i:Number=0;i<20;i++)
				{
					var o:DataObject = new DataObject();
					o.selected=false;
					o.index = i;
					o.name = "test"+(i+1);
					o.phone = "10010-"+(i+1);
					arr.addItem(o);
				}
				setData(arr);
			}
			
			public function setData(arr:ArrayCollection):void
			{
				if(arr.length>0)
				{
					this.obj=arr ;						
				}
			}
			private function call():void
			{
				Alert.show(getSelectedObjects().toString());
			}
			private function getSelectedObjects():ArrayCollection
			{
				var selectedObjects:ArrayCollection=new ArrayCollection();
				if(obj.length>0)
				{
					for(var i:Number=0;i<obj.length;i++)
					{
						var o:DataObject = obj.getItemAt(i) as DataObject;
						if(o.selected)
						{
							selectedObjects.addItem(o.phone);
						}
					}
				}
				return selectedObjects;
			}
			protected function checkbox2_changeHandler(event:Event):void
			{
				var slc:Boolean = selectAllCheckBox.selected;
				if(obj.length>0)
				{
					for(var i:Number=0;i<obj.length;i++)
					{
						obj.getItemAt(i).selected=slc;
					}
				}
				
			}
			
			protected function checkbox3_changeHandler(event:Event):void
			{
				if(obj.length>0)
				{
					for(var i:Number=0;i<obj.length;i++)
					{
						obj.getItemAt(i).selected=!obj.getItemAt(i).selected;
					}
				}
			}
			
		]]>
	</mx:Script>
	<mx:VBox>
		<mx:DataGrid  id="dg"
					  width="100%" height="300"
					  dataProvider="{obj}">
			<mx:columns>
				<mx:DataGridColumn width="16">
					<mx:itemRenderer>
						<mx:Component>
							<mx:CheckBox selected="{data.selected}" change="checkbox1_changeHandler(event)">
								<mx:Script>
									<![CDATA[
										protected function checkbox1_changeHandler(event:Event):void
										{//将复选框的状态保存在obj中,防止出现复选框错乱的情况 
											outerDocument.obj.getItemAt(outerDocument.dg.selectedIndex).selected=event.target.selected; 
										}
										
									]]>
								</mx:Script>
							</mx:CheckBox>
						</mx:Component>
					</mx:itemRenderer>
				</mx:DataGridColumn>
				<mx:DataGridColumn headerText="名称" dataField="name"/>
				<mx:DataGridColumn headerText="电话" dataField="phone"/>
			</mx:columns>
		</mx:DataGrid>
		<mx:HBox>
			<mx:CheckBox label="全选" id="selectAllCheckBox" change="checkbox2_changeHandler(event)"/>
			<mx:CheckBox label="反选" change="checkbox3_changeHandler(event)"/>
		</mx:HBox>
		<mx:Button label="呼叫" click="call()"/>
	</mx:VBox>
</mx:Application>


运行即可。此方法,用全选和反选,不过全选和反选按钮是单独存在,不在Datagrid内


第三种方法

VO

package vos
{
    [Bindable]
    public class TestVO
    {
        public function TestVO()
        {
        }
        
        public var id:String;
        public var label:String;
        public var icon:String;
        
        [Transient]
        public var selected:Boolean = false;
    }
}

<?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">
    
    <s:layout>
        <s:VerticalLayout paddingTop="5" paddingBottom="5" paddingLeft="5" paddingRight="5" gap="5" 
                          horizontalAlign="center" verticalAlign="middle"/>
    </s:layout>
    
    
    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.events.FlexEvent;
            
            import vos.TestVO;
            [Bindable]
            private var dp:ArrayCollection;
            
            
            private function createData():void
            {
                dp = new ArrayCollection();
                for (var i:int = 0; i < 10; i++) 
                {
                    var t:TestVO = new TestVO();
                    t.id = String(i);
                    t.label = "label" + i;
                    t.icon = "assets/icons/" + i + ".png";
                    t.selected = (Math.random() > .5) ? true : false;
                    
                    dp.addItem(t);
                }
                
            }
            
            private function deleteData():void
            {
                for (var i:int = dp.length - 1; i >= 0; i--) 
                {
                    var t:TestVO = dp.getItemAt(i) as TestVO;
                    if(t.selected)
                        dp.removeItemAt(i);
                }
                
            }
            
            public function selectAll(event:MouseEvent):void
            {
                var cb:mx.controls.CheckBox = event.currentTarget as mx.controls.CheckBox;
                
                if(!dp)
                {
                    //还没数据的时候,你就别选中了,没用
                    cb.selected = false;
                    return;
                }
                
                for each (var t:TestVO in dp) 
                {
                    t.selected = cb.selected;
                }
            }
        >>
    </fx:Script>
    
    <fx:Declarations>
        <!-- 将非可视元素(例如服务、值对象)放在此处 -->
    </fx:Declarations>
    
    <mx:DataGrid id="dg" width="400" height="300" dataProvider="{dp}">
        <mx:columns>
            <mx:DataGridColumn width="20" sortable="false">
                <mx:headerRenderer>
                    <fx:Component>
                        <mx:CheckBox click="outerDocument.selectAll(event)"/>
                    </fx:Component>
                </mx:headerRenderer>
                <mx:itemRenderer>
                    <fx:Component>
                        <mx:CheckBox selected="@{data.selected}"/>
                    </fx:Component>
                </mx:itemRenderer>
            </mx:DataGridColumn>
            <mx:DataGridColumn dataField="label"/>
            <mx:DataGridColumn dataField="icon"/>a
        </mx:columns>
    </mx:DataGrid>
    <s:HGroup>
        <s:Button label="create data" click="createData()"/>
        <s:Button label="delete selected data" click="deleteData()"/>
    </s:HGroup>
</s:Application>



几个可能有疑问的地方: 

(1)selected="@{data.selected}", "@"的作用是双向绑定,当data.selected改变时,checkbox的selected也随之改变,反之亦然。

(2)[Transient] 作用是指定接下来的字段在序列化的时候可以忽略。比如与后台交互的时候,后台vo不需要selected这个字段,加上它就行了(不加可能会导致警告)。

(3)例子里的CheckBox没有居中,如果要让它居中可以给它包上一个居中的容器。


用Hbox包一下就行了
<mx:DataGridColumn width="20" sortable="false" textAlign="center">  
    <mx:headerRenderer>  
        <fx:Component>
            <mx:HBox horizontalAlign="center" verticalAlign="middle">
                <mx:CheckBox click="outerDocument.selectAll(event)"/>
            </mx:HBox>
        </fx:Component>  
    </mx:headerRenderer>  
    <mx:itemRenderer>
        <fx:Component>
            <mx:HBox horizontalAlign="center" verticalAlign="middle">
                <mx:CheckBox selected="@{data.selected}"/>
            </mx:HBox>
        </fx:Component>  
    </mx:itemRenderer>  
</mx:DataGridColumn>