简体   繁体   中英

Flex: Binding between components

Simplified example below

I have 2 visual components (PersonPicker and PersonViewer) that need to correspond when an object (Person) changes.

The setter of the PersonViewer apparently does not get called even though the value of the person in that component is changed. I need this because when the value of the person changes, I need to call another function (calculateSalary).

This function initially gets called correctly, but when changing the person in the PersonPicker, the setter is no longer called, which results in the salary label holding on to the initial value.

Person class

package
{
    [Bindable]
    public class Person
    {
        private var _name:String;

        public function Person()
        {
        }

        public function get name():String
        {
            return _name;
        }

        public function set name(value:String):void
        {
            _name = value;
        }

    }
}

Main application

<?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="955" minHeight="600" xmlns:local="*"
               creationComplete="creationCompleteHandler(event)">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>
    <fx:Script>
        <![CDATA[
            import mx.binding.utils.BindingUtils;
            import mx.events.FlexEvent;

            protected function creationCompleteHandler(event:FlexEvent):void
            {
                // Bind the person property of the personPicker to the person property of the personViewer
                BindingUtils.bindProperty(personViewer, "person", personPicker, "person");

                // Create a new Person and set this as the PersonPicker's person
                var john:Person = new Person();
                john.name = "John";
                personPicker.person = john;
            }

        ]]>
    </fx:Script>
    <local:PersonPicker id="personPicker"/>
    <local:PersonViewer id="personViewer"/>
</s:Application>

PersonPicker

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
         xmlns:s="library://ns.adobe.com/flex/spark" 
         xmlns:mx="library://ns.adobe.com/flex/mx" 
         width="100%" height="100">
    <fx:Script>
        <![CDATA[
            private var _person:Person;

            [Bindable]
            public function get person():Person
            {
                return _person;
            }

            public function set person(value:Person):void
            {
                _person = value;
            }

        ]]>
    </fx:Script>
    <s:DropDownList selectedItem="@{person.name}">
        <mx:ArrayCollection>
            <fx:String>Phil</fx:String>
            <fx:String>Bill</fx:String>
            <fx:String>John</fx:String>
            <fx:String>Mike</fx:String>
        </mx:ArrayCollection>
    </s:DropDownList>
</s:Group>

PersonViewer

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
         xmlns:s="library://ns.adobe.com/flex/spark" 
         xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100">
    <fx:Script>
        <![CDATA[
            private var _person:Person;
            [Bindable]
            public function get person():Person
            {
                return _person;
            }
            public function set person(value:Person):void
            {
                trace ("set person()");

                _person = value;

                calculateSalary();
            }

            private function calculateSalary():void
            {
                trace ("calculateSalary()");
                switch (person.name)
                {
                    case "Phil":
                        salary.text = "1000";
                        break;
                    case "Bill":
                        salary.text = "1200";
                        break;
                    case "John":
                        salary.text = "1400";
                        break;
                    case "Mike":
                        salary.text = "1600";
                }
            }
        ]]>
    </fx:Script>
    <s:layout>
        <s:HorizontalLayout/>
    </s:layout>
    <s:Label text="{person.name}"/>
    <s:Label id="salary"/>
</s:Group>

I think this has something to do with changing only the property 'name' of the Person object, which does not cause the setter to be called. Is this correct, and if so, how can I correct my example?

In PersonPicker you are not setting the person property by selecting an item in the dropdown, you are only setting its name .

One way to fix this would be something like this (you bind to the person property instead of its name ):

<s:DropDownList selectedItem="@{person}" labelField="name">
    <mx:ArrayCollection>
        <m:Person name="Phil" />
        <m:Person name="Bill" />
        <m:Person name="John" />
        <m:Person name="Mike" />
    </mx:ArrayCollection>
</s:DropDownList>

Also, there's no reason to use BindingUtils here. Just write:

<local:PersonPicker id="personPicker"/>
<local:PersonViewer id="personViewer" person="{personPicker.person}" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM