When a property is the source of a data binding expression,
Flex automatically copies the value of the source property to any
destination property when the source property changes. To signal
to Flex to perform the copy, you must use the [Bindable] metadata
tag to register the property with Flex, and the source property
must dispatch an event.
The [Bindable] metadata tag has the following
syntax:
[Bindable]
[Bindable(event="eventname")]
If you omit the event name, Flex automatically creates an event
named propertyChange of type PropertyChangeEvent.
You can use the [Bindable] metadata tag in three
places:
Before a public class definition.
The [Bindable] metadata
tag makes usable as the source of a binding expression all public
properties that you defined as variables, and all public properties
that are defined by using both a setter and a getter method. In
this case, [Bindable] takes no parameters, as the
following example shows:
[Bindable]
public class TextAreaFontControl extends TextArea {}
The
compiler automatically generates an event named propertyChange, of
type PropertyChangeEvent, for all public properties so that the
properties can be used as the source of a data binding expression.
If
the property value remains the same on a write, Flex does not dispatch
the event or update the property, where not the same translates
to the following test:
(oldValue !== value)
That
means if a property contains a reference to an object, and that
reference is modified to reference a different but equivalent object,
the binding is triggered. If the property is not modified, but the
object that it points to changes internally, the binding is not
triggered.
Note: When you use the [Bindable] metadata
tag before a public class definition, it only applies to public
properties; it does not apply to private or protected properties,
or to properties defined in any other namespace. You must insert
the [Bindable] metadata tag before a nonpublic property to make it usable as the source for a data binding expression.
Before a public, protected, or private property defined as
a variable to make that specific property support binding.
The
tag can have the following forms:
[Bindable]
public var foo:String;
The Flex compiler automatically
generates an event named propertyChange, of type
PropertyChangeEvent, for the property. If the property value remains
the same on a write, Flex does not dispatch the event or update
the property.
You can also specify the event name, as the
following example shows:
[Bindable(event="fooChanged")]
public var foo:String;
In this case, you are responsible
for generating and dispatching the event, typically as part of some
other method of your class. You can specify a [Bindable] tag
that includes the event specification if you want
to name the event, even when you already specified the [Bindable] tag
at the class level.
Before a public, protected, or private property defined by
a getter or setter method.
You must define both a setter and
a getter method to use the [Bindable] tag with
the property. If you define just a setter method, you create a write-only
property that you cannot use as the source of a data-binding expression. If
you define just a getter method, you create a read-only property
that you can use as the source of a data-binding expression without
inserting the [Bindable] metadata tag. This is
similar to the way that you can use a variable, defined by using
the const keyword, as the source for a data binding
expression.
The tag can have the following forms:
[Bindable]
public function set shortNames(val:Boolean):void {
...
}
public function get shortNames():Boolean {
...
}
The Flex compiler automatically generates an event
named propertyChange, of type PropertyChangeEvent,
for the property. If the property value remains the same on a write,
Flex does not dispatch the event or update the property. To determine
if the property value changes, Flex calls the getter method to obtain
the current value of the property.
You can specify the event
name, as the following example shows:
[Bindable(event="changeShortNames")]
public function set shortNames(val:Boolean):void {
...
// Create and dispatch event. dispatchEvent(new Event("changeShortNames"));
}
// Get method.
public function get shortNames():Boolean {
...
}
In this case, you are responsible for generating
and dispatching the event, typically in the setter method, and Flex
does not check to see if the old value and the new value are different.
You can specify a [Bindable] tag that includes
the event specification to name the event, even
when you already specified the [Bindable] tag at
the class level.
The following example makes the maxFontSize and minFontSize properties
that you defined as variables that can be used as the sources for
data bindings:
// Define public vars for tracking font size.
[Bindable]
public var maxFontSize:Number = 15;
[Bindable]
public var minFontSize:Number = 5;
In the following example, you make a public property that you
defined by using a setter and a getter method that is usable as
the source for data binding The [Bindable] metadata
tag includes the name of the event broadcast by the setter method
when the property changes:
// Define private variable.
private var _maxFontSize:Number = 15;
[Bindable(event="maxFontSizeChanged")]
// Define public getter method.
public function get maxFontSize():Number {
return _maxFontSize;
}
// Define public setter method.public function set maxFontSize(value:Number):void {
if (value <= 30) {
_maxFontSize = value;
} else _maxFontSize = 30;
// Create event object.
var eventObj:Event = new Event("maxFontSizeChanged");dispatchEvent(eventObj);
}
In this example, the setter updates the value of the property,
and then creates and dispatches an event to invoke an update of
the destination of the data binding.
In an MXML file, you can make all public properties that you
defined as variables usable as the source for data binding by including
the [Bindable] metadata tag in an <fx:Metadata> block,
as the following example shows:
<fx:Metadata>
[Bindable]
</fx:Metadata>
You can also use the [Bindable] metadata tag
in an <fx:Script> block in an MXML file to
make individual properties that you defined as variables usable as
the source for a data binding expression. Alternatively, you can
use the [Bindable] metadata tag with properties
that you defined by using setter and getter methods.
Using read-only properties as the source for data binding
You
can automatically use a read-only property defined by a getter method, which
means no setter method, as the source for a data-binding expression.
Flex performs the data binding once when the application starts.
Because
the data binding from a read-only property occurs only once at application
start up, you omit the [Bindable] metadata tag
for the read-only property.
Using static properties as the source for data binding
You can
use a static variable as the source for a data-binding expression.
Flex performs the data binding once when the application starts,
and again when the property changes.
You can automatically
use a static constant as the source for a data-binding expression.
Flex performs the data binding once when the application starts. Because
the data binding occurs only once at application start up, you omit
the [Bindable] metadata tag for the static constant.
The following example uses a static constant as the source for a
data-binding expression:
<?xml version="1.0"?>
<!-- binding/StaticBinding.mxml -->
<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">
<fx:Script>
<![CDATA[
// This syntax casues a compiler error.
// [Bindable]
// public static var varString:String="A static var.";
public static const constString:String="A static const.";
]]>
</fx:Script>
<!-- This binding occurs once at application startup. -->
<s:Button label="{constString}"/>
</s:Application>
The executing SWF file for the previous example is shown below:
Working with bindable property chains
When you specify a property
as the source of a data binding expression, Flex monitors not only
that property for changes, but also the chain of properties leading
up to it. The entire chain of properties, including the source property,
is called a bindable property chain. In the following example, firstName.text is a
bindable property chain that includes both a firstName object
and its text property:
<s:Label id="myText" text="{firstName.text}"/>
You
can have a fairly long bindable property chain, as the following
example shows:
For
the data binding mechanism to detect changes to the text property,
only the text property has to be bindable. However,
if you want to assign a new value to any part of the chain at runtime,
every element in the chain must be bindable. Otherwise, modifying
the user, name, or firstName property
at runtime results in the data binding mechanism no longer being
able to detect changes to the text property.
When
using the BindingUtils.bindProperty() or BindingUtils.bindSetter() method,
you specify the bindable property chain as an argument to the method.
For example, the bindProperty() method has the
following signature:
public static function bindProperty(site:Object, prop:String, host:Object, chain:Object,
commitOnly:Boolean = false):ChangeWatcher
The host and chain arguments
specify the source of the data binding expression. You can define
a data binding expression by using the bindProperty() method,
as the following example shows:
In
this example, ["name","firstName","text"] defines
the bindable property chain relative to the user object. Notice
that user is not part of the bindable property
change in this example.
In an MXML data-binding expression,
the bindable property chain is always relative to this.
Therefore, to define a data binding equivalent to the MXML data
binding expression shown above, you write the bindProperty() method
as the following example shows: