Listing 1 DataGrid.as, the first version with "destination-awareness"

// DataGrid.as
package com.theriabook.controls {
	import mx.controls.DataGrid;

	public class DataGrid  extends mx.controls.DataGrid {

	import mx.rpc.remoting.mxml.RemoteObject;
	import mx.rpc.AbstractOperation;
	import mx.rpc.events.*;
	import mx.controls.Alert;
	import mx.managers.CursorManager;

	public var destination:String=null, method : String = null;
	public var autoFill : Boolean = true;
	protected var ro:RemoteObject = null;

	public function fill(... args): void {
		if( ro==null ) {
			if( destination==null || destination.length==0 )
				throw new Error("No destination specified");
			if( method==null || method.length==0 )
				throw new Error("No retrieveMethod specified");

			ro = new RemoteObject(destination);
			ro.showBusyCursor = true;
			ro.concurrency    = "last";
			ro.addEventListener(ResultEvent.RESULT, ro_onResult);
			ro.addEventListener(FaultEvent.FAULT,   ro_onFault);
		}
		var operation:AbstractOperation = ro.getOperation(method);
		operation.arguments = args;
		operation.send();

	}
	private function ro_onFault(evt:FaultEvent):void {
     CursorManager.removeBusyCursor();
		Alert.show("Failed retrieving data: "+evt.message, "[DestinationAwareDataGrid]" + id);
	}

	private function ro_onResult(evt:ResultEvent):void {
      CursorManager.removeBusyCursor();
		if (evt.result.length != 0)
			dataProvider = evt.result;
	}
	}
}

Listing 2 LabelFunctionFormattingDemo.mxml

<?xml version="1.0" encoding="utf-8"?>
<!-- LabelFunctionFormattingDemo.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" layout="vertical"
 xmlns:fx="com.theriabook.controls.*">
	<fx:DataGrid  id="dg" creationComplete="dg.fill()"
		destination="com_theriabook_composition_EmployeeDAO" method="getEmployees" >
		<fx:columns>
			<mx:Array>
				<mx:DataGridColumn    dataField="EMP_LNAME"   />
				<mx:DataGridColumn    dataField="EMP_FNAME"  />
				<mx:DataGridColumn    dataField="PHONE"  labelFunction="phoneLabelFunction" />
				<mx:DataGridColumn    dataField="SS_NUMBER" labelFunction="ssnLabelFunction"  />
			</mx:Array>
		</fx:columns>
	</fx:DataGridEx>
	<mx:Script>
		<![CDATA[
			import mx.formatters.SwitchSymbolFormatter;
			private var sf:SwitchSymbolFormatter;
			private function ssnLabelFunction(item:Object, column:DataGridColumn):String {
				if (!sf) {
					sf = new SwitchSymbolFormatter();
				}
				return sf.formatValue("###-##-####", item["SS_NUMBER"]);
    		}
			private function phoneLabelFunction(item:Object, column:DataGridColumn):String {
				if (!sf) {
					sf = new SwitchSymbolFormatter();
				}
				return sf.formatValue("(###)###-####", item[column.dataField]);
    		}
		]]>
	</mx:Script>
</mx:Application>

Listing 3 DataGridColumn.as, the first version

// DataGridColumn.as (first version)
package com.theriabook.controls.dataGridClasses  {
	import mx.controls.dataGridClasses.DataGridColumn;

	public class DataGridColumn  extends mx.controls.dataGridClasses.DataGridColumn {
		public function  set formatString( fs:String ) : void{
			FormattingManager.setFormat (this, fs);
		}
	}
}


Listing 4 FormattingManager.as, the first version

// FormattingManager.as, first version

package com.theriabook.controls.dataGridClasses
{
	public class FormattingManager
	{
			import mx.controls.dataGridClasses.DataGridColumn;
			import mx.formatters.SwitchSymbolFormatter;
			private static var sf:SwitchSymbolFormatter;

			public static function setFormat(dgc:mx.controls.dataGridClasses.DataGridColumn ?
			formatString:String):void {
				switch (formatString.toLowerCase()) {
					case "ssn":
						dgc.labelFunction = ssnLabelFunction;
					case "phone":
						dgc.labelFunction = phoneLabelFunction;
				}
			}
			private static function ssnLabelFunction(item:Object, column:
			mx.controls.dataGridClasses.DataGridColumn):String {
				if (!sf) {
					sf = new SwitchSymbolFormatter();
				}
				return sf.formatValue("###-##-####", item["SS_NUMBER"]);
    			}
			private static function phoneLabelFunction(item:Object, column:DataGridColumn):String {
				if (!sf) {
					sf = new SwitchSymbolFormatter();
				}
				return sf.formatValue("(###)###-####", item[column.dataField]);
    			}

	}
}

Listing 5 A simple application illustrating FormattingManager.as

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"  layout="vertical"
xmlns:fx="http://www.theriabook.com/2006">
	<fx:DataGrid  id="dg" creationComplete="dg.fill()"
	destination="com_theriabook_composition_EmployeeDAO" method="getEmployees" >
		<fx:columns>
			<mx:Array>
				<mx:DataGridColumn    dataField="EMP_LNAME"   />
				<mx:DataGridColumn    dataField="EMP_FNAME"  />
				<fx:DataGridColumn    dataField="PHONE"  formatString="phone" />
				<fx:DataGridColumn    dataField="SS_NUMBER" formatString="ssn"  />
			</mx:Array>
		</fx:columns>
	</fx:DataGridEx>
</mx:Application>

Listing 6 MaskFormatter.as

//MaskFormatter.as

package com.theriabook.formatters {
	import mx.formatters.Formatter;
	import mx.formatters.SwitchSymbolFormatter;

	public class MaskFormatter extends  Formatter {
		private var formatString:String;
		private var sf:SwitchSymbolFormatter;
		public function MaskFormatter( fs:String) {
			formatString = fs;
			sf = new SwitchSymbolFormatter();
		}
		public override function format(val:Object):String {
			return sf.formatValue( formatString, val);
		}
	}
}

Listing 7 FormattingManager.as

//com.theriabook.controls.dataGridClasses.FormattingManager.as

package com.theriabook.controls.dataGridClasses
{
	public class FormattingManager
	{
		   import mx.controls.dataGridClasses.DataGridColumn;
		   import mx.formatters.*;
			import com.theriabook.formatters.MaskFormatter;

			public static function setFormat(
				dgc:mx.controls.dataGridClasses.DataGridColumn,
				formatString:String):void {
	 			var  formatter:Formatter = null;
				switch (formatString.toLowerCase()) {
					case "ssn":
						formatter = new MaskFormatter("###-##-####");
						break;
					case "money":
						formatter = new CurrencyFormatter();
						CurrencyFormatter(formatter).precision=2;
						break;
					case "phone":
						formatter = new PhoneFormatter();
						break;
	 				case "shortdate":
						formatter = new DateFormatter();	
						break;
	 				case "zip":
						formatter = new ZipCodeFormatter();	
						break;
					}
					if (formatter) {
						dgc.labelFunction = function (
							item:Object,
							dgc:mx.controls.dataGridClasses.DataGridColumn):String
						{
							return formatter.format(item[dgc.dataField]);
						}
					}
			}
	}
}

Listing 8 FormatStringDemo.mxml

<?xml version="1.0" encoding="utf-8"?>
<!-- FormatStringDemo.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"  layout="vertical"
xmlns:fx="http://www.theriabook.com/2006">
	<fx:DataGrid  id="dg" creationComplete="dg.fill()"
	destination="com_theriabook_composition_EmployeeDAO" method="getEmployees" >
		<fx:columns>
			<mx:Array>
				<mx:DataGridColumn    dataField="EMP_LNAME"   />
				<mx:DataGridColumn    dataField="EMP_FNAME"  />
				<fx:DataGridColumn    dataField="SALARY" formatString="money" />
				<fx:DataGridColumn    dataField="PHONE" formatString="phone" />
				<fx:DataGridColumn    dataField="SS_NUMBER" formatString="ssn" />
			</mx:Array>
		</fx:columns>
	</fx:DataGrid>
</mx:Application>

Listing 9 FormattingManager.as, the complete listing

//FormattingManager.as
package com.theriabook.controls.dataGridClasses
{
	public class FormattingManager
	{
		import mx.controls.dataGridClasses.DataGridColumn;
		import mx.formatters.*;
		import com.theriabook.formatters.MaskFormatter;

		public static function setFormat(
			dgc:mx.controls.dataGridClasses.DataGridColumn,
			formatData:Object):void {

			var  formatter:Formatter = null;
			var  fs:String;
			if (formatData is String)
				fs = formatData as String;
			else
				fs = formatData.formatString;

			switch (fs.toLowerCase()) {
				case "ssn":
					formatter = new MaskFormatter("###-##-####");
					break;
				case "money":
					formatter = new CurrencyFormatter();
					CurrencyFormatter(formatter).precision=2;		
					break;
				case "phone":
					formatter = new PhoneFormatter();
					break;
				case "shortdate":
					formatter = new DateFormatter();
					break;
				case "zip":
					formatter = new ZipCodeFormatter();			
					break;
				default:
					if (fs.indexOf("#")!=-1) {
						formatter = new MaskFormatter(fs);		
						};
			}
			if (!(formatData is String)) {
				for (var property:String in formatData) {
					try {
						formatter[property] = formatData[property];
					} catch (err:Error) {
						// Property does not match formatter type
					}
				}
			}
			if (formatter) {
				dgc.labelFunction = function (
					item:Object,
					dgc:mx.controls.dataGridClasses.DataGridColumn
				):String {
					return formatter.format(item[dgc.dataField]);
				}
			}
		}

	}
}

Listing 10 FormatDataDemo.mxml

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"  layout="vertical"
xmlns:fx="http://www.theriabook.com/2006">
	<!-FormatDataDemo.mxml -->
	<fx:DataGrid  id="dg" creationComplete="dg.fill()"
	destination="com_theriabook_composition_EmployeeDAO" method="getEmployees"  >
		<fx:columns>
			<mx:Array>
				<mx:DataGridColumn    dataField="EMP_LNAME"   />
				<mx:DataGridColumn    dataField="EMP_FNAME"  />
				<fx:DataGridColumn    dataField="BIRTH_DATE"  formatString="shortdate"/>
				<fx:DataGridColumn    dataField="SALARY" >
					<fx:formatData>
						<mx:Object formatString="money" precision="0"/>
					</fx:formatData>
				</fx:DataGridColumn>
				<fx:DataGridColumn  dataField="PHONE">
					<fx:formatData>phone</fx:formatData>
				</fx:DataGridColumn>
				<fx:DataGridColumn  dataField="SS_NUMBER" formatString="ssn" />
			</mx:Array>
		</fx:columns>
	</fx:DataGrid>
</mx:Application>

Listing 11 CheckBox.as, first version

//CheckBox.as
package com.theriabook.controls
{
 import mx.controls.CheckBox;
 
 public class CheckBox extends mx.controls.CheckBox
 {
 
	public var onValue:Object=true;
	public var offValue:Object=false;
	private var _value:Object;

  	public function set value(val:Object) :void {
		_value = val;
		invalidateProperties();
  	}
	public function get value():Object  {
		return selected?onValue:offValue;
	}
	override protected function commitProperties():void {
		selected = (_value == onValue);
		super.commitProperties();
	}
}
}

Listing 12 DataGridColumn, third version

//DataGridColumn.as
package com.theriabook.controls.dataGridClasses{
	import mx.controls.dataGridClasses.DataGridColumn;

	public class DataGridColumn  extends mx.controls.dataGridClasses.DataGridColumn {
 		public function set extendedProperties(val:Object) :void {
				this.itemRenderer["properties"] = val;
		}

		public function  set formatString( fs :String ) : void{
			FormattingManager.setFormat(this, fs);
		}

		public function  set formatData( fd :Object ) : void{
			FormattingManager.setFormat(this, fd);
		}
	}
}

Listing 13 ExtendedPropertiesDemo.mxml

<?xml version="1.0" encoding="utf-8"?>
<!-- ExtendedPropertiesDemo.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"  layout="vertical"
xmlns:fx="http://www.theriabook.com/2006">
	<fx:DataGrid  id="dg" creationComplete="dg.fill()"
	destination="com_theriabook_composition_EmployeeDAO" method="getEmployees"  >
		<fx:columns>
			<mx:Array>
				<mx:DataGridColumn    dataField="EMP_LNAME"   />
				<mx:DataGridColumn    dataField="EMP_FNAME"  />
				<fx:DataGridColumn  dataField="BENE_DAY_CARE" itemRenderer="com.theriabook.controls.CheckBox" >
					<fx:extendedProperties>
						<mx:Object onValue="Y" offValue="N" />
					</fx:extendedProperties>
				</fx:DataGridColumn>
				</mx:Array>
		</fx:columns>
	</fx:DataGrid>
</mx:Application>

Listing 14 Using CheckBox as a inline renderer

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="vertical" xmlns:fx="com.theriabook.controls.*">
	<fx:DataGrid  id="dg"
			destination="com_theriabook_composition_EmployeeDAO"
			method="getEmployees"    creationComplete="dg.fill()"	>
		<fx:columns>
			<mx:Array>
				<mx:DataGridColumn    dataField="EMP_LNAME"   />
				<mx:DataGridColumn    dataField="EMP_FNAME"  />
				<mx:DataGridColumn    dataField="BENE_DAY_CARE">
					<mx:itemRenderer>
						<mx:Component>
							<fx:CheckBox onValue="Y" offValue="N"/>
						</mx:Component>
					</mx:itemRenderer>
				</mx:DataGridColumn>
			</mx:Array>
		</fx:columns>
	</fx:DataGrid>
</mx:Application>

Listing 15 CheckBox.as, the second version

//CheckBox.as
package com.theriabook.controls
{
 import flash.events.Event;
 import mx.controls.CheckBox;
 import mx.controls.dataGridClasses.DataGridListData;
 import mx.core.mx_internal;
 use namespace mx_internal;
 
 public class CheckBox extends mx.controls.CheckBox
 {
	public var onValue:Object=true;
	public var offValue:Object=false;
	private var _value:*;

	public function CheckBox() {
		super();
		addEventListener(Event.CHANGE,
			function(event:Event):void{
	 			if (listData) {
	  				data[DataGridListData(listData).dataField] = value;
	 			}
			}
		);
	}

  	public function set value(val:*) :void {
		_value = val;
		invalidateProperties();
  	}
	public function get value():Object  {
		if (_value==undefined)
		  return _value;
		else
		  return selected?onValue:offValue;
	}
	override protected function commitProperties():void {
		if (_value!=undefined)
			selected = (_value == onValue);
		super.commitProperties();
	}

	override public function set data(item:Object):void	{
		super.data = item;
		if( item!=null ) {
			value = item[DataGridListData(listData).dataField];
		}
	}

	 override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void
	{

		super.updateDisplayList(unscaledWidth, unscaledHeight);
		if (currentIcon) {
			var style:String = getStyle("textAlign");
			if ((!label) && (style=="center") ) {
				currentIcon.x = (unscaledWidth - currentIcon.measuredWidth)/2;
			}
			currentIcon.visible = (_value!=undefined);
		}
	}
 }
}

Listing 16 UndefinedCheckBoxDemo.mxml

<?xml version="1.0" encoding="utf-8"?>
<!-- UndefinedCheckBoxDemo.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"  layout="vertical"
xmlns:fx="http://www.theriabook.com/2006">
	<mx:Button label="Revoke day care benefit"
	click="dg.selectedItem.BENE_DAY_CARE=undefined;
		       dg.dataProvider.itemUpdated(dg.selectedItem);" />
	<fx:DataGrid  id="dg" creationComplete="dg.fill();dg.selectedIndex=0;"
	destination="com_theriabook_composition_EmployeeDAO" method="getEmployees"  >
		<fx:columns>
			<mx:Array>
				<mx:DataGridColumn    dataField="EMP_LNAME"   />
				<mx:DataGridColumn    dataField="EMP_FNAME"  />
				<fx:DataGridColumn  dataField="BENE_DAY_CARE" textAlign="center"
					itemRenderer="com.theriabook.controls.CheckBox" >
					<fx:extendedProperties>
						<mx:Object onValue="Y" offValue="N" />
					</fx:extendedProperties>
				</fx:DataGridColumn>
				</mx:Array>
		</fx:columns>
	</fx:DataGrid>

</mx:Application>

}
</cfscript>
</cffunction>