i have a component which gets the data selected by the radio button
<mx:itemRenderer >
<fx:Component id="radio">
<mx:RadioButton selected="false" useHandCursor="true" change="item_changeHandler(event)">
<fx:Script>
<![CDATA[
private var data_id:int;
private var data_name:String;
protected function item_changeHandler(event:Event):void
{
data_id=data.id;
data_name=data.name;
}
]]>
</fx:Script>
</mx:RadioButton>
</fx:Component>
</mx:itemRenderer>
here there are 2 variables data_id and data_name and i want to use this component variables in the main application which get called when i click a button so what to do how do i call the variables values into this function i tried this
protected function delete_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
dispatchEvent( new Event( Event.CHANGE ) );
deleteTaxonomy(data.id, data.name);
}
If I understand you correctly, then I would dispatch an event when the id and name changes and catch it in the main application. E.g. you could create a CustomEvent class YouDataEvent.as with the variables id and name. I often use this with my own objects and then send the object with the event. Lets call your object containing the id and name YourObject
import flash.events.Event;
public class YourObjectEvent extends Event
{
public static const YOURDATA_UPDATED:String = "yourdataUpdated";
public var yourObj:YourObject
public function YourObjectEvent(type:String, yourObjInput:YourObject, bubbles:Boolean = true, cancelable:Boolean = false)
{
this.yourObj = yourObjInput;
super(type, bubbles, cancelable);
}
}
Then you can dispatch the event when the data changes e.g. in the *item_changeHandler* method like so:
dispatchEvent(new YourObjectEvent(YourObjectEvent.YOURDATA_UPDATED, yourObjVar));
And catch it at the main application with e.g.:
FlexGlobals.topLevelApplication.addEventListener(YourObjectEvent.YOURDATA_UPDATED, yourObjUpdatedHandler);
private function yourObjUpdatedHandler(event:YourObjectEvent): void {
//DO something
var id:Number = event.yourObj.id;
var name:String = event.yourObj.name
}
Hope this helps!
Related
I would like to programmatically change a selected item, in a tree or list, to the item currently "marked/focused" under the mouse pointer .
I'm working with an Flex Air standalone application.
I was thinking in the lines of:
myTree.selectedItem = EVENT.TARGET (where EVENT could be a mouseover/rightclick/rollOver event, and TARGET should be the node/item currently under the mouse pointer).
Is there a way of doing this (or in any other way)?
Ahh, and i want to do it without left clicking ;-)
Thank you in advance,
Sebastian
I found this interesting enough so I am asking if this is the easiest way to achieve this. First off, instead of the list, you need to add the rollOver-listener to the ItemRenderer, not to the list itself (as the event.target and event.currentTarget will just show your list).
So lets create a custom ItemRenderer and add a rollOver listener
<xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true" height="20" rollOver="itemrenderer1_rollOverHandler(event)">
<fx:Script>
<![CDATA[
protected function itemrenderer1_rollOverHandler(event:MouseEvent):void
{
this.dispatchEvent(new CustomEvent(CustomEvent.SELECT_ITEM, data, true));
}
]]>
<s:Label id="label1" text="{data.label}"/>
</s:ItemRenderer>
You need to somehow get the value of the selected item (which is the data on the itemRenderer) so I created a CustomEvent-class just to do so.
package
{
import flash.events.Event;
public class CustomEvent extends Event
{
public var selectedItem:Object;
public static const SELECT_ITEM:String = "selectItem";
public function CustomEvent(type:String, selectedItem:Object, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
this.selectedItem = selectedItem;
}
}
}
then I added a eventListener to the main class and set the list.selectedItem property accordingly:
//for the main MXML initializer:
this.addEventListener(CustomEvent.SELECT_ITEM, rollOverChangeSelected);
//and the function:
protected function rollOverChangeSelected(ce:CustomEvent):void{
list.selectedItem = ce.selectedItem;
}
Another way: bindable variable
The list:
s:List id="list" allowMultipleSelection="true" selectionColor="red" rollOverColor="red" itemRenderer="customItemRenderer" selectedItem="{_rollOverSelectedItem}">
The variable and set / get methods:
[Bindable] public var _rollOverSelectedItem:Object;
public function get rollOverSelectedItem():Object
{
return _rollOverSelectedItem;
}
public function set rollOverSelectedItem(value:Object):void
{
_rollOverSelectedItem = value;
}
and the ItemRenderer's rollOver-method:
protected function itemrenderer1_rollOverHandler(event:MouseEvent):void
{
this.parentApplication.rollOverSelectedItem = data;
}
What is the best/proper way?
I have a class in Flex that crates a custom IconItemRenderer by extending the IconItemRenderer base class. I'm using this custom item within a list and listen to mouse press. Depending on the location of the mouse press, I have different options. One of which is to navigate to a different view. I know how to use the change listener of the list to push to a new view but don't want to implement it. The idea for the mouse click is that depending on the location, I can remove elements from the list or open up the current element.
For the life of me I cannot find a method to navigate to a new view from within the IconItemRenderer. This is the code I'm using, both the class and the list where I implement it.
package components
{
import spark.components.Button;
import spark.components.IconItemRenderer;
import spark.utils.MultiDPIBitmapSource;
public class DeleteItemRenderer extends IconItemRenderer
{
private var btn:Button;
private var xIcon:MultiDPIBitmapSource;
public function DeleteItemRenderer()
{
super();
super.iconWidth = super.iconHeight = 40;
super.labelField = 'title';
super.decorator = "assets/delete.png";
}
override public function set data(value:Object):void{
super.data = value;
}
override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void{
setElementPosition(decoratorDisplay, unscaledWidth-40, 5);
setElementSize(decoratorDisplay, 40, 40);
}
override protected function measure():void{
measuredHeight = 50;
}
override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void{
graphics.beginFill(0xffffff);
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
graphics.endFill();
decoratorDisplay.smooth = true;
graphics.lineStyle(1,0xcccccc,1);
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
graphics.endFill();
}
}
}
List
<s:List id="survey_list" visible="true" width="98%" height="70%" contentBackgroundColor="#FFFFFF" horizontalCenter="0">
<s:itemRenderer>
<fx:Component>
<components:DeleteItemRenderer width="99.9%" height="98%" verticalAlign="top" click="detectActionPress();">
<fx:Script>
<![CDATA[
import spark.components.ViewNavigator;
import spark.components.View;
import mx.events.FlexEvent;
import mx.core.FlexGlobals;
import mx.core.UIComponent;
import spark.components.List;
private var application:UIComponent = FlexGlobals.topLevelApplication as UIComponent;
private var pressOpen:Number = application.width - 40;
//private var _navigator:ViewNavigator = FlexGlobals.topLevelApplication.navigation; //navigation is not defined uhhhh why????
private function detectActionPress():void{
var localX:Number = this.mouseX;
if(localX <= pressOpen){
engangeElement();
}
else{
deleteElement();
}
}
private function deleteElement():void{
var parentList:List = owner as List;
parentList.dataProvider.removeItemAt(parentList.dataProvider.getItemIndex(data));
trace('element removed');
}
private function engangeElement():void{
var parentList:List = owner as List;
var _test:ViewNavigator = this.parentDocument as ViewNavigator;
//this.parentApplication.navigator.pushView(views.UnfinishedSurvey, parentList.selectedItem.shortcode)
_test.pushView(views.UnfinishedSurvey, parentList.selectedItem.shortcode);
}
]]>
</fx:Script>
</components:DeleteItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:List>
Any ideas how I could push a new view from engageElement();
Why don't I have access to the navigator?
Thanks
Generally; I would recommend dispatching an event from inside the itemRenderer. Be sure that the event bubbles.
You can listen to the event on a class which is a hierarchical parent of the itemRenderer / List.
In the event handler you can access the navigator.
I wrote about the approaches here; which may provide more details.
There are alternate ways to do this. You could use a class that has an instance to the navigator and inject that into your renderer using some type of dependency injenction (DI) framework. Robotlegs and Swiz are two ActionScript based frameworks that support this.
I'm doing a project using Java + Flex. I created Java class and used Flex remote object to invoke the method. When I write all the code in an mxml, it runs well. But when I wrap the script in an as file, there's something curious. I need to click twice on Flex button to get the result which returned by the remote object. I think there's something wrong with my as file.
Below is my MXML:
<?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="500" minHeight="600">
<fx:Declarations>
<mx:RemoteObject id="Control" destination="Control" showBusyCursor="true" />
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.wntime.ControlUtil;
import mx.rpc.events.ResultEvent;
private var resultOfCmd:String;
private var cmdStr:String;
private var ct:ControlUtil = new ControlUtil();
/* invoke as method */
private function test():void
{
cmdStr = cmdTxt.text;
resultOfCmd = ct.exec(cmdStr);
cmdConsole.text = resultOfCmd;
}
/* */
private function exec():void{
cmdStr = cmdTxt.text;
Control.execCmd(cmdStr);
Control.addEventListener(ResultEvent.RESULT,execCmd_clickHandler);
}
private function execCmd_clickHandler(event:ResultEvent):void
{
cmdConsole.text = event.result.toString();
}
private function clearCmdConsole():void
{
cmdConsole.text = "";
}
]]>
</fx:Script>
<s:Panel id="CmdPanel" x="70" y="50" width="501" height="350" title="Command Execute Panel">
<s:RichText x="20" y="33" fontSize="14" text="Cmd:"/>
<s:TextInput id="cmdTxt" x="60" y="30" width="239"/>
<s:Button id="execCmd" x="312" y="30" width="68" label="execute" click="exec()"/>
<s:Button x="400" y="30" label="CmdTest" click="test()"/>
<s:TextArea id="cmdConsole" x="20" y="85" width="450" editable="false"/>
<s:Button x="400" y="250" label="clear" click="clearCmdConsole()"/>
</s:Panel>
</s:Application>
Here is the as file which named ControlUtil:
package com.wntime{
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.remoting.RemoteObject;
public class ControlUtil
{
private var cmd:String = null;
private var result:String = null;
private var roControl:RemoteObject = new RemoteObject();
public function ControlUtil()
{
roControl.destination = "Control";
}
public function exec(_cmd:String):String{
this.cmd = _cmd;
roControl.execCmd(cmd);
roControl.addEventListener(FaultEvent.FAULT, execCmd);
roControl.addEventListener(ResultEvent.RESULT, execCmd);
return result;
}
public function execCmd(event:ResultEvent):void
{
setResult(event.result.toString());
}
public function setResult(_result:String):void
{
this.result = _result;
}
}
}
If I click the execute button. The result will show in the console(the textarea) directly.
But I need to click twice on CmdTest button to get the result to show in the console.
Give me a hand plz.Thanks in advance.
This is just a wild guess, but I think the method you invoke at the Java side returns faster than you add your listeners, hence no event handler is called. The second time all listeners are in place and your call succeeds. Try adding your listeners before you invoke remote method.
Your code has various errors/problem in my opinion, I would do something like that:
package com.wntime{
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.remoting.RemoteObject;
public class ControlUtil
{
private var cmd:String = null;
private var result:String = null;
private var roControl:RemoteObject = new RemoteObject();
// the callBack function is the function that is called when the
// remoteobject successfully or not complete the request...
// you can set as parameters anything you want...
private var callBack:Function = null;
public function ControlUtil()
{
roControl.destination = "Control";
}
public function exec(callBack:Function, _cmd:String):void{
this.cmd = _cmd;
this.callBack = callBack;
roControl.addEventListener(FaultEvent.FAULT, errorCmd);
roControl.addEventListener(ResultEvent.RESULT, execCmd);
roControl.execCmd(cmd);
}
private function execCmd(event:ResultEvent):void
{
callBack(true,event.result.toString());
}
private function errorCmd(event:FaultEvent):void
{
callBack(false, event.error); // call the callBack function passing the value you need
}
}
}
the callBack function is something like that:
private function name(b:Boolean, s:String = null){....}
* EDIT *
from your main code you invoke the exec command...
// function invoked when the button is clicked!
private function buttonClick():void
{
var tmp:ControlUtil = new ControlUtil();
//exec(callBack:Function, _cmd:String)
//you pass the function as a reference so when the async request is terminated the function is invoked and you can parse the result....
tmp.exec(getResult, "cmqString");
}
// callBack function for the method ControlUtil.exec
private function getResult(b:Boolean, result:String = ""):void
{
if (b)
{
// the call returned correctly and the result variable contains the value.
}
else
{
// the call failed and the result variable contains the error
}
}
Both the boolean and the result value are returned because I specified it in the ControlUtil when i used callBack(true/false, result/error)
You can create the function as you prefer...
I have noticed an unexpected behaviour with binding in Flex, my code is as follow :
Application code
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" horizontalAlign="center" xmlns:Model="Model.*">
<mx:Script>
<![CDATA[
import Model.DataDummy;
]]>
</mx:Script>
<mx:HBox width="100%" horizontalGap="30">
<mx:Button id="buttonChange1" label="Change property value" click="myDummy._resetMyProperty();" />
<mx:Label id="labelRaw" text="{'My Property=' + myDummy.MyProperty}" opaqueBackground="#DDDDDD" />
<mx:Label id="labelFormatted" text="{'My Property formatted=' + myDummy.MyPropertyFormatted}" opaqueBackground="#DDDDDD" />
</mx:HBox>
<Model:MyDummy id="myDummy" />
<mx:DataGrid id="dataGrid"
width="100%" dataProvider="{DataDummy.Dummies}">
<mx:columns>
<mx:DataGridColumn dataField="MyProperty" headerText="My property" />
<mx:DataGridColumn dataField="MyPropertyFormatted" headerText="My property Formatted" />
</mx:columns>
</mx:DataGrid>
<mx:Button id="buttonChange2" click="{for each ( var d:MyDummy in DataDummy.Dummies ){d._resetMyProperty();}}" label="Change property value in DataGrid" />
</mx:Application>
Model.MyDummy class code
package Model
{
import flash.events.EventDispatcher;
import mx.formatters.NumberFormatter;
import mx.utils.StringUtil;
[Bindable]
public class MyDummy extends EventDispatcher
{
/*** Constructor ***/
public function MyDummy()
{
this._resetMyProperty();
}
/*** Properties ***/
private var _myProperty:Number;
public function get MyProperty():Number
{
return _myProperty;
}
public function set MyProperty(value:Number):void
{
if ( value !== _myProperty )
{
_myProperty = value;
//var event:Event = new Event("ID_Changed");
//this.dispatchEvent(event);
}
}
//[Bindable (event="ID_Changed", type="flash.events.Event")]
public function get MyPropertyFormatted():String
{
var idFormatted:String = "";
if ( ! isNaN(this.MyProperty) )
{
var formatter:NumberFormatter = new NumberFormatter();
formatter.precision = 2;
idFormatted = formatter.format(this.MyProperty);
}
else
idFormatted = MyProperty.toString();
return StringUtil.substitute( "{0} (My property has been formatted)", idFormatted );
}
/*** Methods ***/
public function _resetMyProperty():void
{
this.MyProperty = Math.round(Math.random() * 1000000000);
}
}
}
Model.DataDummy class code
package Model
{
import mx.collections.ArrayCollection;
public class DataDummy
{
private static var _dummies:ArrayCollection;
public static function get Dummies():ArrayCollection
{
if ( _dummies == null )
{
_dummies = new ArrayCollection();
_dummies.addItem(new MyDummy());
_dummies.addItem(new MyDummy());
}
return _dummies;
}
}
}
The behaviour is as follow :
When I click on buttonChange1, _resetMyProperty is called on the instance myDummy.
The result is that the label "labelRaw" has its text changed and the label "labelFormatted" does not have its text changed. This does happen because MyPropertyFormatted is a readonly property and that readonly properties are binded only at the initialisation of the application and not afterwards, according to Flex documentation. With this, I agree.
When I click on buttonChange2, resetMyProperty method is called on every MyDummy element of the ArrayCollection Model.DataDummy.Dummies (this static property is binded to the DataGrid).
The result is that both columns of the DataGrid have their values changed, despite the fact that the DataGrid's second column is linked to the same readonly property MyPropertyFormatted of the MyDummy objects. I find this inconsistent with the previous behaviour I described.
My point is that :
1. On one hand, because I'm binding my controls to a single instance of an certain object, binding won't trigger on his readonly properties.
2. On the other hand, when I'm binding a control on a collection of the same certain objects, binding will trigger on every properties (readonly or not).
If I want binding to be triggered on readonly properties in point 1, I have to dispatch an event and precise on the readonly properties' MetaTag that their binding will be triggered according to this event (as show the commentaries in the code of the class Model.MyDummy class).
Why is this behaviour different ? I would like to precisely understand what an ArrayCollection instance's binding does that a single instance's binding does not.
Thank you for your help.
I suppose the right code is something like the following.
First, our model.MyDummy class:
package model
{
import flash.events.EventDispatcher;
import mx.events.PropertyChangeEvent;
import mx.formatters.NumberFormatter;
import mx.utils.StringUtil;
public class MyDummy extends EventDispatcher
{
//------------------------------------------------------------------------------
//
// Constructor
//
//------------------------------------------------------------------------------
public function MyDummy()
{
resetMyProperty();
}
//------------------------------------------------------------------------------
//
// Properties
//
//------------------------------------------------------------------------------
//--------------------------------------
// myProperty
//--------------------------------------
private var _myProperty:Number;
[Bindable(event="propertyChange")]
public function get myProperty():Number
{
return _myProperty;
}
public function set myProperty(value:Number):void
{
if (_myProperty == value)
return;
var oldPropertyValue:Number = _myProperty;
var oldFormatted:String = myPropertyFormatted;
_myProperty = value;
dispatchEvent(PropertyChangeEvent.createUpdateEvent(this, "myProperty", oldPropertyValue, value));
dispatchEvent(PropertyChangeEvent.
createUpdateEvent(this, "myPropertyFormatted", oldFormatted, myPropertyFormatted));
}
[Bindable(event="propertyChange")]
public function get myPropertyFormatted():String
{
var idFormatted:String = "";
if (!isNaN(myProperty))
{
var formatter:NumberFormatter = new NumberFormatter();
formatter.precision = 2;
idFormatted = formatter.format(myProperty);
}
else
idFormatted = myProperty.toString();
return StringUtil.substitute("{0} (My property has been formatted)", idFormatted);
}
//------------------------------------------------------------------------------
//
// Methods
//
//------------------------------------------------------------------------------
public function resetMyProperty():void
{
myProperty = Math.round(Math.random() * 1000000000);
}
}
}
We're firing propertyChange event to have possibility to fire collectionChangeEvent from our ArrayCollection (it listens propertyChange event automatically).
Then our model.DataDummy class:
package model
{
import mx.collections.ArrayCollection;
import mx.events.CollectionEvent;
public class DataDummy
{
//------------------------------------------------------------------------------
//
// Constructor
//
//------------------------------------------------------------------------------
public function DataDummy()
{
dummies = new ArrayCollection();
dummies.addItem(new MyDummy());
dummies.addItem(new MyDummy());
}
//------------------------------------------------------------------------------
//
// Variables
//
//------------------------------------------------------------------------------
[Bindable]
public var dummies:ArrayCollection;
}
}
We don't use statics to have advantage of data binding with [Bindable] metatag.
And finally our main class with minimal changes:
<mx:Application horizontalAlign="center" layout="vertical" xmlns:model="model.*" xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
//------------------------------------------------------------------------------
//
// Event Handlers
//
//------------------------------------------------------------------------------
protected function buttonChange2_clickHandler(event:MouseEvent):void
{
for each (var d:MyDummy in dataProvider.dummies)
{
d.resetMyProperty();
}
}
]]>
</mx:Script>
<mx:HBox horizontalGap="30" width="100%">
<mx:Button click="myDummy.resetMyProperty();" id="buttonChange1" label="Change property value" />
<mx:Label id="labelRaw" opaqueBackground="#DDDDDD" text="{'My Property=' + myDummy.myProperty}" />
<mx:Label id="labelFormatted" opaqueBackground="#DDDDDD"
text="{'My Property formatted=' + myDummy.myPropertyFormatted}" />
</mx:HBox>
<model:MyDummy id="myDummy" />
<model:DataDummy id="dataProvider" />
<mx:DataGrid dataProvider="{dataProvider.dummies}" id="dataGrid" width="100%">
<mx:columns>
<mx:DataGridColumn dataField="myProperty" headerText="My property" />
<mx:DataGridColumn dataField="myPropertyFormatted" headerText="My property Formatted" />
</mx:columns>
</mx:DataGrid>
<mx:Button click="buttonChange2_clickHandler(event)" id="buttonChange2" label="Change property value in DataGrid" />
</mx:Application>
As you can see all the bindings works as expected.
P.S. [Bindable(event="propertyChange")] is an equivalent of simple [Bindable] but this way you can avoid compiler warnings on myPropertyFormatted getter. Actually, using simple [Bindable] form causes mxmlc compiler to generate dispatchEvent code by itself. And you can use pointing a particular event in [Bindable] tag to have more control. For example in our case we can fire event for myPropertyFormatted.
P.P.S. I've changed your C#-like naming conventions to reflect actual ActionScript/MXML ones.
I want to capture a change in a property of an item as follows
myItem.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,listener);
protected function listener(event:PropertyChangeEvent):void {
...
}
the problem i'm having is that when I assign multiple values to the "myItem" object the listened gets kicked off multiple times. for instance
If I do:
myItem.x = new_x;
myItem.y = new_y;
....
the listener kicks off everytime a change happens (after calling first line, then after calling second line..etc). How to prevent that to save processing/memory and avoid inconsistency.
You can listen for Event.COMPLETE (or create a custom event) and manually dispatch that when you've finished changing all your properties. For example:
myItem.addEventListener(Event.COMPLETE, listener);
protected function listener(e:Event):void
{
...
}
then
myItem.x = newX;
myItem.y = newY;
myItem.dispatchEvent(new Event(Event.COMPLETE));
You can override the setter of your component and dispatch a custom event
You can use mx.utils.ObjectProxy class and by overriding its protected "setupPropertyList" method you can specify by youself what properties will trigger PropertyChangeEvent.PROPERTY_CHANGE event
You could do that the "hackish" way. Example follows...
BindingObject.as:
package bindings
{
import mx.core.EventPriority;
import mx.events.PropertyChangeEvent;
import mx.events.PropertyChangeEventKind;
[Bindable]
public class BindingObject
{
private var inEditMode : Boolean = false;
public function BindingObject()
{
this.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, onPropertyChange, false, EventPriority.BINDING - 1);
}
private function onPropertyChange(event : PropertyChangeEvent) : void
{
if (inEditMode)
event.stopImmediatePropagation();
}
public function beginEdit() : void
{
inEditMode = true;
}
public function endEdit() : void
{
inEditMode = false;
this.dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE, false, false, PropertyChangeEventKind.UPDATE));
}
public var myX : int = 0;
public var myY : int = 0;
}
}
testapplication.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="onCreationComplete();">
<mx:Script>
<![CDATA[
import mx.events.PropertyChangeEvent;
import bindings.BindingObject;
[Bindable]
private var something : BindingObject = new BindingObject();
private function onCreationComplete() : void
{
something.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, listener);
something.beginEdit();
trace("Begun edit");
trace("changing myX");
something.myX = 3;
trace("changed myX");
trace("changing myY");
something.myY = 6;
trace("changed myY");
trace("Ending edit");
something.endEdit();
trace("Ended");
}
private function listener(event : PropertyChangeEvent) : void
{
trace("in my listener");
}
private function myX(val : int) : String
{
trace("in myX");
return val.toString();
}
private function myY(val : int) : String
{
trace("in myY");
return val.toString();
}
]]>
</mx:Script>
<mx:Label text="{myX(something.myX)}" />
<mx:Label text="{myY(something.myY)}" />
</mx:Application>
So, as you can see, I've added an event listener in the class to be bound, that will be triggered right after the generated binding listeners (note the priority is BINDING - 1) and in there I stop the propagation of the event. Which means whatever listeners still need to be executed, won't. The endEdit method will dispatch the PropertyChange event that will trigger your listener.
Now, assuming that you do something costly in your listener this should solve your problem.