<?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" minWidth="955" minHeight="600">
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.events.DataGridEvent;
import mx.events.DataGridEventReason;
import mx.controls.TextInput;
import mx.validators.StringValidator;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
public var nv:StringValidator;
//Some data to populate the datagrid... you would probably get this from a Database in reality
[Bindable]
public var arData:ArrayCollection = new ArrayCollection([
{relationship:'Friend',firstname:'Tariq',lastname:'',country:'USA'},
{relationship:'Friend',firstname:'Jon',lastname:'Hirschi',country:'CAN'},
{relationship:'Boss',firstname:'Ryan',lastname:'Stewart',country:'CAN'},
{relationship:'Family',firstname:'Mark',lastname:'Davies',country:'USA'}
]);
//Fired when the user clicks into a datagrid cell
private function onEditBeginning(event:DataGridEvent):void
{
var dataField:String = event.dataField;
var relationship:String = dg.selectedItem.relationship;
var country:String = dg.selectedItem.country;
//We only want to allow editing of friends. If it's any other relationship, stop right now.
if(relationship!='Friend')
{
Alert.show('Sorry dude, you can only edit your Friends.');
event.preventDefault();
}
else
{
//Check if this is a column we want to allow editing
//Ya, you could do <mx:DataGridColumn editable="false" etc.../>
//But this gives you an idea if you needed to do it conditionally based on the situation.
if(dataField!='lastname')
{
Alert.show('Bro, you can only edit the last name.');
event.preventDefault();
}
else
{
if(country!='USA')
{
Alert.show('You can only edit if the country is USA');
event.preventDefault();
}
}
}
}
private function checkIt(myEvent:Event):void
{
dg.invalidateList();
}
//This gets fired when the itemEditor is about to be destroyed. As a result of hitting enter, tab, or mouse clicking away.
private function onEditEnd(event:DataGridEvent):void
{
var dataField:String = event.dataField;
var fCell:Array=[event.columnIndex,event.rowIndex];
//This tells us what the new data is about to be before it's committed.
var newData:String = TextInput(event.currentTarget.itemEditorInstance).text;
nv = new StringValidator();
//This if statement isn't nescessary in this example. But say you needed to validate
//different cells differently... here's where you'd check which cell we're dealing with.
if(dataField == 'lastname')
{
//specify the source - in this case the itemEditor instance
//We only care to do this if they started typing in something
nv.source = event.currentTarget.itemEditorInstance;
nv.property = "text";
nv.minLength = 3;
nv.requiredFieldError = "at least 3 chars required";
nv.tooShortError = "at least 3 chars required";
var val:* = nv.validate();
if(val.type == "invalid")
{
event.preventDefault();
if(newData.length!=0)
callLater(maintainEdit,fCell); //if they typed in something and it didn't validate
} //we want to get Flex to re-invoke the editor on this cell.
else //**NOTE: Once this function onEditEnd completes, the validator won't highlight
{ //the cell anymore, because the itemEditor gets destroyed...
callLater(maintainFocus);
}
}
else
callLater(maintainFocus);
}
//this checks to see if we're still in edit mode, and if we're not..invoke it
private function maintainEdit(colIndex:int,rowIndex:int):void
{
var editCell:Object = {columnIndex:colIndex, rowIndex: rowIndex};
if(dg.editedItemPosition==null)
{
//This will invoke the datagrid's itemEditBegin
dg.editedItemPosition = editCell;
//Because the itemEditor got destroyed, in the above line we're essentially creating a new itemEditor
//So we want to invoke the validator right away so we can highlight to the user that we're not happy
//With the validation...
callLater(validateCurrentEditor);
}
}
private function validateCurrentEditor():void
{
if(dg.itemEditorInstance!=null)
{
nv.source = dg.itemEditorInstance;
nv.validate();
}
}
//prevents enter/tab from moving onto the next cell after finishing editing.
private function maintainFocus():void
{
dg.editedItemPosition = null;
}
]]>
</fx:Script>
<mx:Panel title="Conditional Cell Editing Example" horizontalCenter="0" verticalCenter="0">
<mx:Text width="300" text="This is an example of maintaining edit on the cell if validation fails,stays on the cell if the user commits via enter/tab click (but allows mouse click off the cell if the cell is empty),and only allows editing of the Last Name column if the Country is USA."/>
<mx:DataGrid dataProvider="{arData}" height="100%" width="100%" editable="true"
itemEditBeginning="onEditBeginning(event)" itemEditEnd="onEditEnd(event)" id="dg" change="checkIt(event)">
<mx:columns>
<fx:Array>
<mx:DataGridColumn dataField="relationship" headerText="Relationship" textAlign="center"/>
<mx:DataGridColumn dataField="firstname" headerText="First Name" textAlign="center"/>
<mx:DataGridColumn dataField="lastname" headerText="Last Name" textAlign="center"/>
</fx:Array>
</mx:columns>
</mx:DataGrid>
<mx:Label text="By Tariq Ahmed. www.cflex.net"/>
</mx:Panel>
</s:Application>