最近,在一个项目中,其中有个UI,需要提供用户自定义DataGrid表头,而DataGrid默认Header是不允许修改的,不过没有关系我们这个可以用DataGridColumn.headerRenderer来实现…

最近,在一个项目中,其中有个UI,需要提供用户自定义DataGrid表头,而DataGrid默认Header是不允许修改的,不过没有关系我们这个可以用DataGridColumn.headerRenderer来实现。

要自定义符合DataGridColumn规范的headerRenderer,必须实现mx.core.IDataRenderer接口,要实现mx.core.IDataRenderer接口需要定义如下两个方法:

[java]
    // Internal variable for the property value.
    private var _data:Object;

    // Define the getter method.
    public function get data():Object {
        return _data;
    }

    // Define the setter method, and dispatch an event when the property
    // changes to support data binding.
    public function set data(value:Object):void {
        _data = value;

        dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
    }

幸运的是,ComboBox、Container、Image、Label、TextArea, TextInput等类都实现了该接口,所以我们这里可以使用如下实现我们的可编辑HeaderRenderer:

[java]
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
       doubleClick="editHeaderView()" doubleClickEnabled="true">
	<mx:Script>
		<![CDATA[
			import mx.controls.dataGridClasses.DataGridColumn;
			import mx.events.FlexEvent;
			[Bindable]
			private var _dgColumn:DataGridColumn;
			/**
		     *  The <code>data</code> property lets you pass a value
		     *  to the component when you use it in an item renderer or item editor.
		     *  You typically use data binding to bind a field of the <code>data</code>
		     *  property to a property of this component.
		     *
		     *  <p>You do not set this property in MXML.</p>
		     *
		     *  @default null
		     *  @see mx.core.IDataRenderer
		     */
		    override public function get data():Object
		    {
		        return _dgColumn;
		    }

		    /**
		     *  @private
		     */
		    override public function set data(value:Object):void
		    {
		        _dgColumn = value as DataGridColumn;
				_dgColumn.sortable=false;
		        dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
		    }
		    private function editHeaderView():void{
		    	_label_mc.visible=false;
		    	_textInput_mc.visible=true;
		    	_textInput_mc.setFocus();
		    }
		    private function setHeaderLabel():void{
		    	_dgColumn.headerText=_textInput_mc.text;
		    	_textInput_mc.visible=false;
		    	_label_mc.visible=true;
		    }

		]]>
	</mx:Script>
	<mx:Label id="_label_mc" top="0" paddingLeft="2" paddingRight="2"
                left="0" right="0" bottom="0" text="{_dgColumn.headerText}"/>
	<mx:TextInput id="_textInput_mc" paddingLeft="2" paddingRight="2"
               borderStyle="none"  top="0" left="0" right="0" bottom="0"
               text="{_dgColumn.headerText}" visible="false" enter="setHeaderLabel()" focusOut="setHeaderLabel()"/>
</mx:Canvas>

Canvas是Container的子类,所以上面的组件实现了mx.core.IDataRenderer接口,另外我们重载了get data()set data()方法,其中set data(value:Object)方法中的参数value就是使用该HeaderRenderer的DataGridColumn。

上面的HeaderRenderer组件中,我们定义了一个Label和一个TextInput构件,初始非编辑状态时Label显示,当用户双击DataGrid的列表头时,Label隐藏,而TextInput显示,这样用户就可以自由编辑Header了,接着我们将DataGridColumn.headerText设置为TextInput.text以保存用户输入。

另外,因为编辑Header与sort排序冲突,所以该组件会自动关闭DataGridColumn.sort=false。

以下是测试代码:

[xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"  layout="vertical">
	<mx:Script>
      <![CDATA[
         import mx.collections.ArrayCollection;

         [Bindable]
         private var dpADG:ArrayCollection = new ArrayCollection([
           {Artist:'Pavement', Album:'Slanted and Enchanted', Price:12.99},
           {Artist:'Pavement', Album:'Brighten the Corners', Price:13.99},
           {Artist:'Saner', Album:'A Child Once', Price:14.99},
           {Artist:'The Doors', Album:'The Best of the Doors', Price:10.99}
         ]);
      ]]>
    </mx:Script>
    <mx:DataGrid dataProvider="{dpADG}">
    	<mx:columns>
    		<mx:DataGridColumn dataField="Artist" width="80"
                       headerRenderer="com.eshangrao.controls.dataGridClasses.EditableDataGridHeaderRenderer"/>
    		<mx:DataGridColumn dataField="Album"  width="200"
                       headerRenderer="com.eshangrao.controls.dataGridClasses.EditableDataGridHeaderRenderer"/>
    		<mx:DataGridColumn dataField="Price"
                         headerRenderer="com.eshangrao.controls.dataGridClasses.EditableDataGridHeaderRenderer"/>
    	</mx:columns>
    </mx:DataGrid>
</mx:Application>

运行示例

本组件已经包含入Plum中,点击这里下载源码及二进制SWC包。