本文使用DataGrid的headerRenderer 和itemRenderer ,设计一个的DataGrid+Checkbox 的组件,且包括了表头多选 支持。
[主程序源码(application.mxml source code)] :
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- http://www.myflexhero.com/share/flex3-mx/flex-mx-core-components/flex-mx-ui-controls/flex-mx-tree-and-datagrid-controls/604 --> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*" height="500" verticalGap="0" viewSourceURL="srcview/index.html"> <mx:Script> <![CDATA[ private var arr:Array = [ { firstName: "Alex", lastName: "Harui", age: 48 }, { firstName: "Gordon", lastName: "Smith", age: 54 }, { firstName: "Deepa", lastName: "Subramanian", age: 22 }, { firstName: "Matt", lastName: "Chotin", age: 28 }, { firstName: "Ely", lastName: "Greenfield", age: 32 }, { firstName: "Kevin", lastName: "Lynch", age: 15}, { firstName: "Shantanu", lastName: "Narayan", age: 50 }, { firstName: "Joan", lastName: "Lafferty", age: 23 }, { firstName: "Ryan", lastName: "Frishberg", age: 19 }, { firstName: "Jason", lastName: "Szeto", age: 30 }, { firstName: "Mark", lastName: "Anders", age: 40 }, { firstName: "Peter", lastName: "Flynn", age: 24 }, { firstName: "Heidi", lastName: "Williams", age: 18 } ]; ]]> </mx:Script> <local:CheckBoxDataGrid id="dg" initialize="dg.dataProvider=arr" horizontalScrollPolicy="on" allowMultipleSelection="true" change="foo.text = dg.selectedIndices.toString()" > <local:columns> <mx:DataGridColumn dataField="firstName" headerText=" " width="20" sortable="false" itemRenderer="CheckBoxRenderer" headerRenderer="CheckBoxHeaderRenderer" > </mx:DataGridColumn> <mx:DataGridColumn dataField="firstName" headerText="First Name" /> <mx:DataGridColumn dataField="lastName" headerText="Last Name" /> </local:columns> </local:CheckBoxDataGrid> <mx:Label id="foo" /> </mx:Application>
[CheckBoxDataGrid.as源码] :
package { import flash.display.Sprite; import flash.events.KeyboardEvent; import mx.controls.CheckBox; import mx.controls.DataGrid; import mx.controls.listClasses.IListItemRenderer; /** * DataGrid that uses checkboxes for multiple selection */ public class CheckBoxDataGrid extends DataGrid { override protected function selectItem(item:IListItemRenderer, shiftKey:Boolean, ctrlKey:Boolean, transition:Boolean = true):Boolean { // only run selection code if a checkbox was hit and always // pretend we're using ctrl selection if (item is CheckBox) return super.selectItem(item, false, true, transition); return false; } // turn off selection indicator override protected function drawSelectionIndicator( indicator:Sprite, x:Number, y:Number, width:Number, height:Number, color:uint, itemRenderer:IListItemRenderer):void { } // whenever we draw the renderer, make sure we re-eval the checked state override protected function drawItem(item:IListItemRenderer, selected:Boolean = false, highlighted:Boolean = false, caret:Boolean = false, transition:Boolean = false):void { if (item is CheckBox) CheckBox(item).invalidateProperties(); super.drawItem(item, selected, highlighted, caret, transition); } // fake all keyboard interaction as if it had the ctrl key down override protected function keyDownHandler(event:KeyboardEvent):void { // this is technically illegal, but works event.ctrlKey = true; event.shiftKey = false; super.keyDownHandler(event); } } }
[CheckBoxRenderer.as源码] :
package { import flash.display.DisplayObject; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.text.TextField; import mx.controls.CheckBox; import mx.controls.dataGridClasses.DataGridListData; import mx.controls.listClasses.ListBase; /** * The Renderer. */ public class CheckBoxRenderer extends CheckBox { public function CheckBoxRenderer() { focusEnabled = false; } override public function set data(value:Object):void { super.data = value; invalidateProperties(); } override protected function commitProperties():void { super.commitProperties(); if (owner is ListBase) selected = ListBase(owner).isItemSelected(data); } /* eat keyboard events, the underlying list will handle them */ override protected function keyDownHandler(event:KeyboardEvent):void { } /* eat keyboard events, the underlying list will handle them */ override protected function keyUpHandler(event:KeyboardEvent):void { } /* eat mouse events, the underlying list will handle them */ override protected function clickHandler(event:MouseEvent):void { } /* center the checkbox if we're in a datagrid */ override protected function updateDisplayList(w:Number, h:Number):void { super.updateDisplayList(w, h); if (listData is DataGridListData) { var n:int = numChildren; for (var i:int = 0; i < n; i++) { var c:DisplayObject = getChildAt(i); if (!(c is TextField)) { c.x = (w - c.width) / 2; c.y = 0; } } } } } }
[CheckBoxHeaderRenderer.as源码] :
package { import flash.display.DisplayObject; import flash.events.Event; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.text.TextField; import mx.controls.CheckBox; import mx.controls.dataGridClasses.DataGridListData; import mx.controls.listClasses.ListBase; /** * The Renderer. */ public class CheckBoxHeaderRenderer extends CheckBox { public function CheckBoxHeaderRenderer() { focusEnabled = false; } override public function set data(value:Object):void { invalidateProperties(); } private var addedListener:Boolean = false; private var partiallySelected:Boolean = false; override protected function commitProperties():void { super.commitProperties(); if (owner is ListBase) { if (!addedListener) { addedListener = true; owner.addEventListener("valueCommit", owner_changeHandler, false, 0, true); owner.addEventListener("change", owner_changeHandler, false, 0, true); } if (ListBase(owner).dataProvider.length == ListBase(owner).selectedItems.length) { selected = true; partiallySelected = false; } else if (ListBase(owner).selectedItems.length == 0) { selected = false; partiallySelected = false; } else { selected = false; partiallySelected = true; } invalidateDisplayList(); } } /* eat keyboard events, the underlying list will handle them */ override protected function keyDownHandler(event:KeyboardEvent):void { } /* eat keyboard events, the underlying list will handle them */ override protected function keyUpHandler(event:KeyboardEvent):void { } override protected function clickHandler(event:MouseEvent):void { if (selected) { // uncheck everything ListBase(owner).selectedIndex = -1; } else { var n:int = ListBase(owner).dataProvider.length; var arr:Array = []; for (var i:int = i; i < n; i++) arr.push(i); ListBase(owner).selectedIndices = arr; } } /* center the checkbox if we're in a datagrid */ override protected function updateDisplayList(w:Number, h:Number):void { super.updateDisplayList(w, h); graphics.clear(); if (listData is DataGridListData) { var n:int = numChildren; for (var i:int = 0; i < n; i++) { var c:DisplayObject = getChildAt(i); if (!(c is TextField)) { c.x = (w - c.width) / 2; c.y = 0; c.alpha = 1; if (partiallySelected) { graphics.beginFill(0x000000); graphics.drawRect(c.x, c.y, c.width, c.height); graphics.endFill(); c.alpha = 0.7; } } } } } private function owner_changeHandler(event:Event):void { invalidateProperties(); } } }