6 Replies Latest reply on Nov 28, 2011 6:29 AM by yancaoshi

    Notify listener by updating property of a bound instance

    yancaoshi

      Hi all,

       

      I met this question because of some restrictions. Generally, I have to use BindingUtils to bind instance and hope listener can react to update of property, not only new reference. Here is my sample coding with only two classes.

       

      User.as

       

      package
      {
                [Bindable]
                public class User
                {
                          public function User()
                          {
                          }
        
                          public var uname:String;
        
                          public var uage:int;
        
                }
      }
      
      

       

      views.UserView.mxml

       

      <?xml version="1.0" encoding="utf-8"?>
      <s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
                                              xmlns:s="library://ns.adobe.com/flex/spark" title="UserView"
                                              creationComplete="view1_creationCompleteHandler(event)">
                <fx:Script>
                          <![CDATA[
                                    import mx.binding.utils.BindingUtils;
                                    import mx.events.FlexEvent;
        
                                    [Bindable]
                                    public var userSource:User;
        
                                    public function set userTarget(value:User):void
                                    {
                                              taUser.text = "Name: " + value.uname + "\n" + "Age: " + value.uage;
                                    }
        
                                    protected function view1_creationCompleteHandler(event:FlexEvent):void
                                    {
                                              userSource = new User();
                                              userSource.uname = "Tom";
                                              userSource.uage = 32;
                                              // Due to business reason, this must be used to bind property.
                                              // I have no choice to bind single property 
                                              BindingUtils.bindProperty(this, "userTarget", this, "userSource");
                                    }
        
                                    /**
                                     * I want userSource get notified by doing anything else here
                                     */
                                    protected function btnAge_clickHandler(event:MouseEvent):void
                                    {
                                              userSource.uname = tiName.text;
                                              userSource.uage = int(tiAge.text);
                                    }
        
                                    /**
                                     * This is usual way, but I don't want to always create new instance to update single property
                                     * especially for those huge class
                                     */
                                    protected function btnUser_clickHandler(event:MouseEvent):void
                                    {
                                              var u:User = new User();
                                              u.uname = tiName.text;
                                              u.uage = int(tiAge.text);
                                              userSource = u;
                                    }
        
                          ]]>
                </fx:Script>
                <s:Label x="10" y="31" text="User Name"/>
                <s:TextInput id="tiName" x="97" y="10" width="82"/>
                <s:Label x="10" y="86" text="User Age"/>
                <s:TextInput id="tiAge" x="97" y="69" width="82"/>
                <s:Button id="btnAge" x="10" y="110" width="169" label="Update Age"
                                                                  click="btnAge_clickHandler(event)"/>
                <s:Button id="btnUser" x="10" y="161" width="169" label="Upate New User"
                                                                  click="btnUser_clickHandler(event)"/>
                <s:TextArea id="taUser" x="207" y="10" width="247" height="195"/>
        
      </s:View>
      
      

       

      Question is How to notify listener by clicking button "Update Age"??

       

       

      Regards,

        • 1. Re: Notify listener by updating property of a bound instance
          yancaoshi Level 1

          Some comments

          Also do I meet a similar case that is ArrayCollection is bindable and listner will be notified if item is added to or removed from ArrayCollection. To case updating item, there are two options. One is setItemAt method which doesn't make sense to me since I still need to create new item. Another option is to call itemUpdated method which I have not managed yet.

           

          Is it possible to update two properties at one time?

          • 2. Re: Notify listener by updating property of a bound instance
            drkstr_1 Level 4

            For your first question, you can bind to any property chain you want.

             

            http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/binding/utils/Bindin gUtils.html#bindProperty()

             

            So you could do something like this to bind to a specific property:

             

            BindingUtils.bindProperty(this, "userName", this, ["userSource", "uname"]);

             

            The bindings will execute if userSource or userSource.uname is updated.

             

             

            I don't quite understand your second question. Bindings will update by default when you add or remove items on an ArrayCollection. Were you running into a problem with this, or just wondering if it's supposed to work that way?

            1 person found this helpful
            • 3. Re: Notify listener by updating property of a bound instance
              yancaoshi Level 1

              Thanks for replying

               

              Your tip is helpful more or less. Sometimes the class contains lots of property which will be shown on the view. But I don't want to use too many bindings because of two reasons.

              1) Simplify coding. I only want to listen whether any property is changed of the instance. If so, I will call a function to set all values at one time. I really don't want to bind all the properties.

              2) Worry about performance. I have used too many bindings already in my mobile project. Though it still runs OK, I am afraid it deteriorate performance. One often used scenario is I set label text with

              label="{resourceManager.getString('LocRes', 'FB_LANGUAGE')}

              It's so simple to write this that I am too lazy to set with AS codings. Is there a simple way to set labe in MXML without binding?

              • 4. Re: Notify listener by updating property of a bound instance
                yancaoshi Level 1

                Regarding my second question, I show a list along with a detail area. User can click a line and edit it in the detail area. When he saves, modification should be updated on the list. I make use of setItemAt with a new item which behaves OK with little impact such as selection is disappeared.

                And now, I listen to PropertyChangeEvent.PROPERTY_CHANGE and update item manually. I think method itemUpdated of ArrayCollection should be the best implementation but cannot make it by now. Adding or removing item is not discussed here but updating item.

                 

                Hope this clarifies my doubt clearly

                 

                 

                Best wishes,

                • 5. Re: Notify listener by updating property of a bound instance
                  drkstr_1 Level 4

                  i think i understand the issue now.

                   

                  You need to create a data model class and specify a custom event to use for binding (see Bindable metadata tag docs). You can use the same event for one or more properties, or all of them if set on the class.

                   

                  I still dont fully understand the second problem, but iassume you mean the labels in some list wont auto update with bindings. Having a fully bindable model class will solve that.

                   

                  *edit*

                   

                  I see you are already using a bindable model so that probably wont help with the second issue. Can you please elaborate on what your expectations are, and what is actually happening instead.

                   

                  ps: sorry foor typos, posting this from phone...

                  • 6. Re: Notify listener by updating property of a bound instance
                    yancaoshi Level 1

                    I wasted lots of time here trying to find out why my item doesn't get updated. And see what I got!

                     

                    In method handlePropertyChangeEvents of class ListCollectionView, I find eventItems get cleared since I set filterFunction but no sort. Please see line 1421, it tries to call method moveItemInView in which localIndex is null because of no sort.

                     

                    It works if I remove my filterFunction.

                     

                    Then I tried to add sort.It is a MUST to call refresh after setting sort otherwise localIndex is still null.

                     

                     

                    It seems working now.

                     

                     

                    BTW: I am working on SDK4.5.1