itemEditBeginning イベントのイベントリスナーから、編集中のセルを調べ、編集できないようにすることができます。特定のセル(複数可)のみを編集禁止とし、それ以外のセルは編集できるようにする場合に、この方法が便利です。
例えば、DataGrid コントロールで editable プロパティを使用して、DataGrid コントロールにあるセルをすべて編集可能にします。DataGridColumn の editable プロパティを使用することで、特定の列についてこの設定を上書きすることはできますが、特定のセルについて編集を有効または無効にすることはできません。
セルを編集できないようにするには、次の例に示すように、itemEditBeginning イベントに設定した独自のイベントリスナーから preventDefault() メソッドを呼び出します。
<?xml version="1.0"?>
<!-- itemRenderers\events\EndEditEventPreventEdit.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.events.DataGridEvent;
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99},
{Artist:'Pavement', Album:'Brighten the Corners',
Price:11.99}
]);
// Define event listener for the cellEdit event
// to prohibit editing of the Album column.
private function disableEditing(event:DataGridEvent):void {
if(event.columnIndex==1)
{
event.preventDefault();
}
}
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
dataProvider="{initDG}"
editable="true"
itemEditBeginning="disableEditing(event);" >
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
前の例で実行する SWF ファイルは以下のとおりです。
前の例では列のインデックスを使用していましたが、DataGrid または編集しているセルの任意のプロパティを調べて、そのセルを編集可能にするかどうかを決めることができます。
itemEditBegin イベントおよび itemEditEnd イベントを使用して、アイテムエディタとの間で受け渡しするデータを調べ、必要に応じてそのデータを変更できます。例えば、データの再フォーマット、編集対象となるデータの部分的抽出、検証のためのデータの調査などが可能です。
次の例では、NumericStepper コントロールを使用して、DataGrid コントロールの Price 列を編集します。この列を編集すると、itemEditBegin イベントにより、NumericStepper に渡されたデータが変更され、自動的に 20 %が価格に上乗せされます。必要に応じて、NumericStepper コントロールを使用して更新された価格を変更します。
<?xml version="1.0"?>
<!-- itemRenderers\events\BeginEditEventAccessEditor.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.events.DataGridEvent;
import mx.controls.NumericStepper;
import mx.collections.ArrayCollection;
import mx.controls.listClasses.IDropInListItemRenderer;
[Bindable]
private var myDP:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted', Price:11.99},
{Artist:'Pavement', Album:'Crooked Rain, Crooked Rain', Price:10.99},
{Artist:'Pavement', Album:'Wowee Zowee', Price:12.99},
{Artist:'Pavement', Album:'Brighten the Corners', Price:11.99},
{Artist:'Pavement', Album:'Terror Twilight', Price:11.99}
]);
// Handle the itemEditBegin event.
private function modifyEditedData(event:DataGridEvent):void
{
// Get the name of the column being editted.
var colName:String = myDataGrid.columns[event.columnIndex].dataField;
if(colName=="Price")
{
// Handle the event here.
event.preventDefault();
// Creates an item editor.
myDataGrid.createItemEditor(event.columnIndex,event.rowIndex);
// All item editors must implement the IDropInListItemRenderer interface
// and the listData property.
// Initialize the listData property of the editor.
IDropInListItemRenderer(myDataGrid.itemEditorInstance).listData =
IDropInListItemRenderer(myDataGrid.editedItemRenderer).listData;
// Copy the cell value to the NumericStepper control.
myDataGrid.itemEditorInstance.data = myDataGrid.editedItemRenderer.data;
// Add 20 percent to the current price.
NumericStepper(myDataGrid.itemEditorInstance).value +=
0.2 * NumericStepper(myDataGrid.itemEditorInstance).value;
}
}
]]>
</mx:Script>
<mx:DataGrid id="myDataGrid" dataProvider="{myDP}"
editable="true"
itemEditBegin="modifyEditedData(event);"
rowHeight="60">
<mx:columns>
<mx:DataGridColumn dataField="Artist" />
<mx:DataGridColumn dataField="Album" width="130" />
<mx:DataGridColumn dataField="Price" editorDataField="value">
<mx:itemEditor>
<mx:Component>
<mx:NumericStepper stepSize="0.01" maximum="500"/>
</mx:Component>
</mx:itemEditor>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>
</mx:Application>
前の例で実行する SWF ファイルは以下のとおりです。
Flex のいずれかのフォーマッタクラスを使用して、アイテムエディタから返されるデータをフォーマットできます。次の例では、DataGrid コントロールの Price 列をユーザーが編集できるようにします。次に、itemEditEnd イベントのイベントリスナーを宣言します。このイベントリスナーでは、次のコードに示すように、NumberFormatter クラスを使用して、セルの新しい値の小数点以下桁数を 2 桁に制限します。
<?xml version="1.0"?>
<!-- itemRenderers\events\EndEditEventFormatter.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Script>
<![CDATA[
import mx.controls.TextInput;
import mx.events.DataGridEvent;
import mx.events.DataGridEventReason;
import mx.formatters.NumberFormatter;
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99},
{Artist:'Pavement', Album:'Brighten the Corners',
Price:11.99 }
]);
// Define the number formatter.
private var myFormatter:NumberFormatter=new NumberFormatter();
// Define the eventlistner for the itemEditEnd event.
public function formatData(event:DataGridEvent):void {
// Check the reason for the event.
if (event.reason == DataGridEventReason.CANCELLED)
{
// Do not update cell.
return;
}
// Get the new data value from the editor.
var newData:String=
TextInput(event.currentTarget.itemEditorInstance).text;
// Determine if the new value is an empty String.
if(newData == "") {
// Prevent the user from removing focus,
// and leave the cell editor open.
event.preventDefault();
// Write a message to the errorString property.
// This message appears when the user
// mouses over the editor.
TextInput(myGrid.itemEditorInstance).errorString=
"Enter a valid string.";
return;
}
// For the Price column, return a value
// with a precision of 2.
if(event.dataField == "Price") {
myFormatter.precision=2;
TextInput(myGrid.itemEditorInstance).text=
myFormatter.format(newData);
}
}
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
dataProvider="{initDG}"
editable="true"
itemEditEnd="formatData(event);" >
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
前の例で実行する SWF ファイルは以下のとおりです。
セル編集のメカニズムは、単一の値をリストコントロールに返すアイテムエディタで使用するように最適化されています。この場合は、リストコントロールの定義で editorDataField プロパティを使用して、セルの新しい値を保持するアイテムエディタのプロパティを指定します。
しかし、単一の値ではない形式でデータを返すアイテムエディタを作成することもあります。複数の値を返す方法として、複数のスカラー値を返す方法と、複数値を収めたオブジェクトを返す方法があります。
単一ではない値を返すには、cellEndEvent について、データをアイテムエディタから取得してリストコントロールの editedItemRenderer プロパティに直接書き込むイベントリスナーを記述します。editedItemRenderer プロパティにデータを書き込むことによって、リストコントロールの対応するデータプロバイダも新しい値で更新されます。
次の例では、コンポーネントとして実装するアイテムエディタを示しています。このコンポーネントでは、TextInput コントロールおよび ComboBox コントロールを使用して、住所の都市名と州名の部分をユーザーが設定できるようにします。
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="yellow">
<!-- itemRenderers\events\myComponents\CityStateEditor.mxml -->
<mx:TextInput id="setCity" width="130" text="{data.City}"/>
<mx:ComboBox id="pickState" selectedItem="{data.State}">
<mx:dataProvider>
<mx:String>AL</mx:String>
<mx:String>AK</mx:String>
<mx:String>AR</mx:String>
<mx:String>CA</mx:String>
<mx:String>MA</mx:String>
</mx:dataProvider>
</mx:ComboBox>
</mx:VBox>
cellEndEvent イベントのイベントリスナーで、リストコントロールの itemEditorInstance プロパティを使用して、TextInput コントロールおよび ComboBox コントロールにある新しい値にアクセスします。その後、editedItemRenderer プロパティにこの新しい値を直接書き込んで、リストコントロールを更新できます。次にこの例を示します。
<?xml version="1.0"?>
<!-- itemRenderers\events\ComplexDGEditorReturnObject.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
width="700">
<mx:Script>
<![CDATA[
import mx.events.DataGridEvent;
import mx.events.DataGridEventReason;
import mx.collections.ArrayCollection;
import myComponents.CityStateEditor;
[Bindable]
public var initDG:ArrayCollection = new ArrayCollection([
{Company: 'Acme', Contact: 'Bob Jones',
Phone: '413-555-1212', City: 'Boston', State: 'MA'},
{Company: 'Allied', Contact: 'Jane Smith',
Phone: '617-555-3434', City: 'SanFrancisco', State: 'CA'}
]);
// Define the event listener.
public function processData(event:DataGridEvent):void {
// Check the reason for the event.
if (event.reason == DataGridEventReason.CANCELLED){
// Do not update cell.
return;
}
if(event.dataField == "City and State")
{
// Disable copying data back to the control.
event.preventDefault();
// Get new city from editor.
myGrid.editedItemRenderer.data.City = CityStateEditor(DataGrid(event.target).itemEditorInstance).setCity.text;
// Get new state from editor.
myGrid.editedItemRenderer.data.State = CityStateEditor(DataGrid(event.target).itemEditorInstance).pickState.selectedItem;
// Close the cell editor.
myGrid.destroyItemEditor();
// Notify the list control to update its display.
myGrid.dataProvider.itemUpdated(event.itemRenderer.data);
}
}
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
rowHeight="75"
dataProvider="{initDG}"
editable="true"
itemEditEnd="processData(event);">
<mx:columns>
<mx:DataGridColumn dataField="Company" editable="false"/>
<mx:DataGridColumn dataField="Contact"/>
<mx:DataGridColumn dataField="Phone"/>
<mx:DataGridColumn dataField="City and State" width="150"
itemEditor="myComponents.CityStateEditor">
<mx:itemRenderer>
<mx:Component>
<mx:Text selectable="false" width="100%"
text="{data.City}, {data.State}"/>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>
</mx:Application>
前の例で実行する SWF ファイルは以下のとおりです。
前の例では、インラインアイテムレンダラーを使用して、DataGrid コントロールの 1 つの列に都市名と州名を表示していました。
itemEditEnd イベントのイベントリスナーでは、編集中の列が都市名と州名の列かどうかを判断します。都市名と州名の列であれば、このイベントリスナーは次のアクションを実行します。
List コントロールおよび Tree コントロールの使用例については、アイテムレンダラーとアイテムエディタの使用を参照してください。
次の例では上記と同じアクションを実行しますが、コンポーネントアイテムエディタではなく、インラインアイテムエディタを使用しています。
<?xml version="1.0"?>
<!-- itemRenderers\events\InlineDGEditorReturnObject.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
width="700">
<mx:Script>
<![CDATA[
import mx.events.DataGridEvent;
import mx.collections.ArrayCollection;
import mx.controls.TextInput;
public var newCity:String;
public var newState:String;
[Bindable]
public var initDG:ArrayCollection = new ArrayCollection([
{Company: 'Acme', Contact: 'Bob Jones',
Phone: '413-555-1212', City: 'Boston', State: 'MA'},
{Company: 'Allied', Contact: 'Jane Smith',
Phone: '617-555-3434', City: 'SanFrancisco', State: 'CA'}
]);
public function processData(event:DataGridEvent):void {
if(event.dataField=='City/State')
{
// Disable copying data back to the control.
event.preventDefault();
myGrid.editedItemRenderer.data.City=
myEditor(myGrid.itemEditorInstance).setCity.text;
myGrid.editedItemRenderer.data.State=
myEditor(myGrid.itemEditorInstance).pickState.selectedItem;
myGrid.destroyItemEditor();
// Notify the list control to update its display.
myGrid.dataProvider.itemUpdated(myGrid.editedItemRenderer);
}
}
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
rowHeight="75"
dataProvider="{initDG}"
editable="true"
itemEditEnd="processData(event);">
<mx:columns>
<mx:DataGridColumn dataField="Company" editable="false"/>
<mx:DataGridColumn dataField="Contact"/>
<mx:DataGridColumn dataField="Phone"/>
<mx:DataGridColumn dataField="City/State" width="150">
<mx:itemRenderer>
<mx:Component>
<mx:Text selectable="false" width="100%"
text="{data.City}, {data.State}"/>
</mx:Component>
</mx:itemRenderer>
<mx:itemEditor>
<mx:Component className="myEditor">
<mx:VBox backgroundColor="yellow">
<mx:TextInput id="setCity" width="130"
text="{data.City}"/>
<mx:ComboBox id="pickState"
selectedItem="{data.State}">
<mx:dataProvider>
<mx:String>AL</mx:String>
<mx:String>AK</mx:String>
<mx:String>AR</mx:String>
<mx:String>CA</mx:String>
<mx:String>MA</mx:String>
</mx:dataProvider>
</mx:ComboBox>
</mx:VBox>
</mx:Component>
</mx:itemEditor>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>
</mx:Application>
前の例で実行する SWF ファイルは以下のとおりです。
<mx:Component> タグには、値 "myEditor" が設定された className プロパティがあります。この className プロパティは、インラインアイテムエディタを表すために Flex で作成されたクラスの名前を定義しています。これは前の例で、コンポーネントアイテムエディタのクラス名を、MXML ファイルの名前で定義していたのと同じです。itemEditEnd イベントのイベントリスナーで、myEditor クラスのプロパティとしての TextInput コントロールおよび ComboBox コントロールにアクセスできます。
DataGrid、List または Tree のいずれかのコントロールの rendererIsEditor プロパティを true に設定すると、このコントロールではデフォルトの TextInput コントロールがアイテムエディタとして使用されます。この設定がない場合は、itemRenderer プロパティで指定されているアイテムレンダラーが使用されます。アイテムレンダラーを指定している場合は、編集可能なコントロールをそのレンダラーで指定し、コントロールの値をユーザーが編集できるようにする必要があります。
例えば、次の例に示すアイテムレンダラーでは、TextInput コントロールを使用してセルの情報を表示し、その内容を編集できるようにしています。
<?xml version="1.0"?>
<!-- itemRenderers\dataGrid\myComponents\MyContactEditable.mxml -->
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Script>
<![CDATA[
// Define a property for returning the new value to the cell.
[Bindable]
public var newContact:String;
]]>
</mx:Script>
<mx:Label id="title" text="{data.label1}"/>
<mx:Label id="contactLabel" text="Last Contacted By:"/>
<mx:TextInput id="contactTI"
editable="true"
text="{data.Contact}"
change="newContact=contactTI.text;"/>
</mx:VBox>
次の例に示すように、このアイテムレンダラーを DataGrid コントロールで使用できます。
<?xml version="1.0"?>
<!-- itemRenderers\dataGrid\MainAppEditable.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
height="700" width="700">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{label1: "Order #2314", Contact: "John Doe",
Confirmed: false, Photo: "john_doe.jpg", Sent: false},
{label1: "Order #2315", Contact: "Jane Doe",
Confirmed: true, Photo: "jane_doe.jpg", Sent: false}
]);
]]>
</mx:Script>
<mx:DataGrid id="myDG"
width="500" height="250"
dataProvider="{initDG}"
variableRowHeight="true"
editable="true">
<mx:columns>
<mx:DataGridColumn dataField="Photo"
editable="false"/>
<mx:DataGridColumn dataField="Contact"
width="200"
editable="true"
rendererIsEditor="true"
itemRenderer="myComponents.MyContactEditable"
editorDataField="newContact"/>
<mx:DataGridColumn dataField="Confirmed"
editable="true"
rendererIsEditor="true"
itemRenderer="mx.controls.CheckBox"
editorDataField="selected"/>
<mx:DataGridColumn dataField="Sent"
editable="true"
rendererIsEditor="false"
itemEditor="mx.controls.CheckBox"
editorDataField="selected"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
前の例で実行する SWF ファイルは以下のとおりです。
前の例では、DataGrid コントロールの 2 番目の列と 3 番目の列で rendererIsEditor プロパティを true に設定することにより、アイテムレンダラーをアイテムエディタとして使用していました。
リストコントロールでも、他のコントロールと同様に、セルに格納されたデータを検証できます。そのためには、データバリデータを実装するアイテムレンダラーまたはアイテムエディタを作成します。データバリデータの詳細については、データ検証を参照してください。
次の例は、アイテムエディタコンポーネントを検証するコードを示しています。このコードでは、TextInput コントロールを使用してフィールドを編集します。この例では、ユーザーの入力を検証するために、TextInput コントロールの text プロパティに PhoneNumberValidator バリデータを割り当てます。
<?xml version="1.0"?>
<!-- itemRenderers\validator\myComponents\EditorPhoneValidator.mxml -->
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Script>
<![CDATA[
// Define a property for returning the new value to the cell.
[Bindable]
public var returnPN:String;
]]>
</mx:Script>
<mx:PhoneNumberValidator id="pnV"
source="{newPN}"
property="text"
trigger="{newPN}"
triggerEvent="change"
required="true"/>
<mx:TextInput id="newPN"
text="{data.phone}"
updateComplete="returnPN=newPN.text;"
change="returnPN=newPN.text;"/>
</mx:VBox>
ユーザーが入力した電話番号が不適切な場合、PhoneNumberValidator によってエディタの周囲に赤いボックスが描画されます。そこにマウスを置くと、検証エラーメッセージが表示されます。
次の例は、このアイテムエディタを使用したアプリケーションのコードを示しています。
<?xml version="1.0" ?>
<!-- itemRenderers\validator\MainDGValidatorEditor.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{name: 'Bob Jones', phone: '413-555-1212',
email: 'bjones@acme.com'},
{name: 'Sally Smith', phone: '617-555-5833',
email: 'ssmith@acme.com'},
]);
]]>
</mx:Script>
<mx:DataGrid id="dg"
width="500" height="200"
editable="true"
dataProvider="{initDG}">
<mx:columns>
<mx:DataGridColumn dataField="name"
headerText="Name" />
<mx:DataGridColumn dataField="phone"
headerText="Phone"
itemEditor="myComponents.EditorPhoneValidator"
editorDataField="returnPN"/>
<mx:DataGridColumn dataField="email" headerText="Email" />
</mx:columns>
</mx:DataGrid>
</mx:Application>
前の例で実行する SWF ファイルは以下のとおりです。
このページに新しいコメントが追加された場合に、電子メールでの通知を希望する。 | コメントレポート