2 Replies Latest reply on Aug 23, 2010 4:22 PM by rtalton

    Two-way bindings on composite objects

    Ansury Level 3

      Does anyone know of a way to get two-way bindings to work for a ComboBox that uses objects (not just simple Strings) which contain other objects?


      For Strings in 'objectToBindWith' bindings work fine of course. But if you have some other type of object inside, the compiler chokes with "Cannot assign to a non-reference value" when doing a 2-way binding.


      public class SomeObject {
           public var name:String;//Two-way works fine for simple types (of course ALL examples use this simple case...)
           public var refData:RefData;//No worky
      public class RefData {
           public var id:Number;
           public var code:String;
           public var description:String;
      private var objectToBindWith:SomeObject;
      private var someReferenceDataList:ArrayCollection; //This would be a list of "RefData" objects in this case.
      <mx:ComboBox dataProvider="{someReferenceDataList}" selectedItem="@{objectToBindWith.refData as RefData}" labelField="description"/>



      Now I would have "hoped" that a two way binding would attempt to select (from the dataProvider list) the matching object (if any) being set as selectedItem, as well as set the value of objectToBindWidth.refData to the selectedItem when that changes... but I guess this is too much to expect?  Are there any simple ways to make this work as intended?

        • 1. Re: Two-way bindings on composite objects
          Ansury Level 3


          <mx:ComboBox id="combobox" dataProvider="{refDP}" labelField="desc"

          valueCommit="{obj.ref = combobox.selectedItem as RefObject}"

          selectedItem="{obj.ref as RefObject}"/>



          Solution above only partly works and mostly sucks, that's a lot of crap just for a two way binding (and that's with unrealistically short variable names and ids), and look at the casts needed.  Ughhh..


          It'd need to be a custom combobox to properly init the selecteditem (via some internal property like labelField or 'code') on top of the above.  What a pain... hmm.

          • 2. Re: Two-way bindings on composite objects
            rtalton Level 4

            Yeah, I don't think this would work because the selectedItem has to part of the dataProvider--not just an object with the same values. Also, you can't use the selectedItem property in MXML.


            So, just to show how it could be made to work, you could use <mx:Binding>, like:



            ...where you define rdObject like:


            private var rdObject:Object = ac1.getItemAt(2);


            Now it will work because rdObject actually points to an item in the Combo Box' dataProvider.


            In order to update the selectedItem property on the fly, you'd have to resort setting it manually as needed, either by changing rdObject, or using a cursor on the dataProvider to search for a given value, then setting selectedItem with that (like, cb1.selectedItem = cursor.current).


            I'd also point out that this really isn't two-way binding that you are attempting; it's more like double-binding on the same component.


            OK, well if you MUST extend ComboBox, you could do this (this is from a custom MXML component I made which extends ComBox, and uses an override on selectedItem):


                        //Used to store a pre-selection default; optional.
                        private var _DEFAULT_SELECTION:Object;


                    public override function set selectedItem(value:Object):void{
                        if (value != this.selectedItem){
                            super.selectedItem = value;
                            //set the default selection here for comparison later.
                            //Store off the _DEFAULT_SELECTION value.
                            //If selectedItem was not specified, _DEFAULT_SELECTION will simply be null.
                            _DEFAULT_SELECTION = value;


            THEN you could access selectedItem directly in MXML, and bind to it.