The problem is to do with item renderers and item editors. The data
passed to these components is in the form of an Object. The Object class
does not implement an IEventDispatcher.

So, why does it think you need an IEventDispatcher? Well, to get an
expression to evaluate in MXML you need to use the squiggly braces. This
is also known as a binding expression. In both the item renderer and
item editor there are binding expressions for data.City and data.State.
data is of type Object so you get an error if you bind to it.

So, how do you fix it? By creating custom item editors and renderers
that don't rely on data binding. Here is the example rewritten that
way...

Application:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml";
layout="absolute" width="700">
     <mx:Script>
         <![CDATA[
             import mx.events.DataGridEvent;
             import mx.events.DataGridEventReason;
             import mx.collections.ArrayCollection;
             import Renderers.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.sel\
ectedItem;

                     // 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="Renderers.CityStateEditor"
itemRenderer="Renderers.CityStateRenderer"/>
         </mx:columns>
     </mx:DataGrid>
</mx:Application>

Item Editor (CityStateEditor.mxml):
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml";
backgroundColor="yellow">
     <mx:Script>
         <![CDATA[
             override public function set data(value:Object):void
             {
                 super.data = value;
                 if(value != null)
                 {
                     setCity.text = value.City;
                     pickState.selectedItem = value.State;
                 }
             }
         ]]>
     </mx:Script>
     <mx:TextInput id="setCity" width="130"/>
     <mx:ComboBox id="pickState">
         <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>

Item Renderer(CityStateRenderer.mxml):
<?xml version="1.0" encoding="utf-8"?>
<mx:Text xmlns:mx="http://www.adobe.com/2006/mxml"; width="100%"
selectable="false">
     <mx:Script>
         <![CDATA[
             override public function set data(value:Object):void
             {
                 super.data = value;
                 if(value != null)
                 {
                     text = data.City + ", " + data.State;
                 }
             }
         ]]>
     </mx:Script>
</mx:Text>

Now, as to why the new city does not display if you click on the
background. This is because the itemEditEnd event does not fire until
you either type <return> or click on another cell. You are still in the
item editor when you immediately click on the yellow background. If you
would like it to update when you click there, you would need to monitor
the focusOut event of the text input in the item editor. You would then
need to fire an event off to the application to update the renderers
data. I will leave that as an exercise for the reader ;-}

--- In [email protected], "mmyszew" <mmys...@...> wrote:
>
> If the Flex 3 "Passing multiple values back from an item editor"
example is run with the debugger, the following messages appear
repeatedly.
>
> warning: unable to bind to property 'State' on class 'Object' (class
is not an IEventDispatcher)
> warning: unable to bind to property 'City' on class 'Object' (class is
not an IEventDispatcher)
>
> In addition, If you enter a new city and immediately click the yellow
background of the city/state cell, the new city doesn't show in the
renderer. However, the new city is there if you get the editor to
display again.
>
> I'm a relative newbie and would like to use this example as a starting
point for an application, but I hesitate to start with something that
looks broken.
>
> Your help would be much appreciated.
>
> Mat Myszewski
>
> Here's the code pasted from the Help files (two files).
>
> <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>
>
> <?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.sel\
ectedItem;
>
>                     // 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>
>

Reply via email to