1. Trang chủ
  2. » Công Nghệ Thông Tin

O’Reilly Programming Flex 2 phần 7 docx

51 378 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 51
Dung lượng 181,22 KB

Nội dung

266 | Chapter 12: Working with Data Example 12-1. User class package com.oreilly.programmingflex.data { public class User { private var _nameFirst:String; private var _nameLast:String; private var _email:String; private var _lastLogin:Date; private var _userType:uint; public function get nameFirst( ):String { return _nameFirst; } public function set nameFirst(value:String):void { _nameFirst = nameFirst; } public function get nameLast( ):String { return _nameLast; } public function set nameLast(value:String):void { _nameLast = nameLast; } public function get email( ):String { return _email; } public function set email(value:String):void { var expression:RegExp = /\b[A-Z0-9._%-]+@[A-Z0-9 ]+\.[A-Z]{2,4}\b/i; if(expression.test(value)) { _email = value; } else { _email = "invalid email"; } } public function get lastLogin( ):Date { return _lastLogin; } public function set lastLogin(value:Date):void { _lastLogin = lastLogin; } public function get userType( ):uint { return _userType; } Using Data Models | 267 You can then create an instance of the model class using MXML or ActionScript. With MXML, you have to define the namespace, then use <namespace:Class> to cre- ate the instance: <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:data="com.oreilly. programmingflex.data.*" layout="absolute"> <data:User id="user" email="example@example.com" lastLogin="{new Date( )}" nameFirst="Abigail" nameLast="Smith" userType="1" /> </mx:Application> With ActionScript, you need to import the class, and then use the constructor as part of a new statement: import com.oreilly.programmingflex.data.User; private var user:User; private function initializeHandler(event:Event):void { user = new User( ); user.email = "example@example.com"; // etc. } In the next section, we’ll look at data binding. If you want to enable the data bind- ing feature for a custom ActionScript-based data model, you must use the [Bindable] metatag when declaring the class: [Bindable] public class User { If you create the instance using MXML, the instance is automatically enabled for data binding, assuming the class uses the [Bindable] metatag. However, if you cre- ate the instance using ActionScript, you must also use the [Bindable] tag when declaring the variable you use to store the reference: [Bindable] private var user:User; We’ll talk more about data binding and the [Bindable] metatag in the next section. public function set userType(value:uint):void { if(userType <= 2) { _userType = userType; } } public function User( ) {} } } Example 12-1. User class (continued) 268 | Chapter 12: Working with Data Data Binding Flex applications typically utilize lots of data retrieved from both RPCs (server-side method calls) and user input collected in forms. One way you can work with data is to use extensive ActionScript. ActionScript provides low-level access to all the data in your Flex application. Yet the ActionScript code can be redundant, and it can be time-consuming to write. Although extensive ActionScript may be necessary in some cases, the Flex framework provides a feature called data binding that simplifies work- ing with data in most cases. Data binding lets you associate data from one object with another. There are lots of ways to use data binding. The following examples list a few of the most common uses for data binding: • Link form input controls (text inputs, checkboxes, etc.) with data models. • Link two or more controls (e.g., display a slider value in a text component). In the following sections, we’ll look at the rules of data binding as well as examples of different ways to use data binding. Understanding Data Binding Syntax There are three ways to apply data binding: • Curly brace ( {}) syntax • <mx:Binding> • BindingUtils Each technique for applying data binding has advantages and disadvantages, which we’ll discuss in the next few sections. Curly braces Using curly braces to apply data binding is the simplest and fastest technique. Throughout the early part of this book, you’ve seen quite a few examples of curly- brace syntax. Placing curly braces around any expression causes it to be evaluated. Consider the following example with a combo box and a text input control: <mx:HBox> <mx:ComboBox id="level"> <mx:Array> <mx:Object label="A" data="1" /> <mx:Object label="B" data="2" /> <mx:Object label="C" data="3" /> <mx:Object label="D" data="4" /> </mx:Array> </mx:ComboBox> <mx:TextInput id="selectedLevel" text="level.value" /> </mx:HBox> Data Binding | 269 In this example, the text attribute of the text input is set to level.value. In that for- mat, the value is interpreted literally, so the string level.value displays in the text input. Changing the text input tag to the following makes a big difference: <mx:TextInput id="selectedLevel" text="{level.value}" /> With this change, the text input now selects the data corresponding to the selected combo box item. As the user selects a different combo box item, the value in the text input also updates. This is because the text level.value is now placed within curly braces, so it is treated as an expression rather than as literal text. More than just evaluating the expression, the curly braces attempt to make a data binding association. If the association is successful, as the value of the target (in the example, the target is level.value) changes, the listening property (the text property of the text input in this example) also updates. The preceding example illustrates this because as the combo box value changes, so does the value displayed in the text input. For a more dramatic example, consider the following: <mx:Panel id="panel" width="{panelWidth.value}" height="{panelHeight.value}"> <mx:NumericStepper id="panelWidth" value="200" minimum="200" maximum="400" stepSize="10" height="22"/> <mx:NumericStepper id="panelHeight" value="200" minimum="200" maximum="400" stepSize="10" height="22"/> </mx:Panel> In this example, the panel contains two nested numeric steppers. The panel uses data binding to link the width property to the value of the first numeric stepper and the height property to the value of the second stepper. The result is that as the user changes the values of the numeric steppers, the width and height of the panel change accordingly. There are many scenarios in which you can use curly brace syntax for data binding. As you’ve seen in the preceding example, you can use the syntax to directly associate a target property with a property of a form control such as a text input. You can also link a value from a control to a data model, as the following example illustrates: <mx:Model id="dataModel"> <userData> <email>{email.text}</email> <phone>{phone.text}</phone> <city>{city.text}</city> <state>{state.value}</state> </userData> </mx:Model> <mx:VBox> <mx:Label text="Email" /> <mx:TextInput id="email" /> <mx:Label text="Phone" /> <mx:TextInput id="phone" /> <mx:Label text="City" /> <mx:TextInput id="city" /> 270 | Chapter 12: Working with Data <mx:Label text="State" /> <mx:ComboBox id="state"> <mx:Array> <mx:Object label="CA" /> <mx:Object label="MA" /> </mx:Array> </mx:ComboBox> </mx:VBox> The preceding code uses data binding to link the values from form controls to a data model. You can use data binding both to assign values to a data model, as in the pre- ceding example, and to retrieve data from a data model and display it. And you can even use data binding in both directions at the same time. The following code, used in conjunction with the preceding example, formats and displays the text from the data model in a text area, updating as the user changes the values in the controls bound to the model: <mx:TextArea width="200" height="200" text="{'Contact Information\nEmail: ' + dataModel.email + '\nPhone: ' + dataModel.phone + '\nLocation: ' + dataModel.city + ', ' + dataModel.state}" /> Perhaps an even more useful example is one in which you use data binding to link data either directly from controls or from a data model to an RPC component such as a RemoteObject component. Using data binding in this way allows you to make RPCs without having to write much, if any, ActionScript. The following example uses data binding to link the data from the data model in the preceding example to a RemoteObject instance as the parameters for a method call: <mx:RemoteObject id="example" destination="exampleService"> <mx:method name="saveContactInformation"> <mx:arguments> <email>{dataModel.email}</email> <phone>{dataModel.phone}</phone> <city>{dataModel.city}</city> <state>{dataModel.state}</state> </mx:arguments> </mx:method> </mx:RemoteObject> As the values in the data model update via data binding, so too will the values in the RemoteObject method arguments update. This allows you to call the method by sim- ply calling a send( ) method with no parameters, as in the following example: <mx:Button label="Save" click="example.saveContactInformation.send( )" /> This is a very simple example of working with RemoteObject. The same principles are true when working with HTTPService and WebService as well. All of these RPC tech- niques are discussed in more detail in Chapter 14. Because curly brace syntax allows you to evaluate any ActionScript expression, you can also use data binding with E4X expressions. That means you can use data bind- ing not only to link XML data with control values, but also to link controls and RPC Data Binding | 271 components to XML values using E4X expressions. For instance, instead of using a Model object, as in the earlier example, you can use an XML object as follows: <mx:XML id="xmlData"> <userData email="{email.text}" phone="{phone.text}" city="{city.text}" state="{state.value}" /> </mx:XML> You can then use E4X expressions to link the text area value to values from the XML object: <mx:TextArea width="200" height="200" text="{'Contact Information\nEmail: ' + xmlData.@email + '\nPhone: ' + xmlData.@phone + '\nLocation: ' + xmlData.@city + ', ' + xmlData.@state}" /> <mx:Binding> The <mx:Binding> tag allows you to do exactly the same things as curly brace syntax, but with MXML tags rather than inline expressions. The <mx:Binding> tag requires the following attributes: source The origin of the data you want to link destination The point which you want notified when the value changes from the source For the following example, the same basic premise is used as in the first example of the curly brace discussion: we’ll link the value from a combo box to a text input so that when the user changes the value in the combo box, the value in the text input also changes. First, we’ll add the controls: <mx:HBox> <mx:ComboBox id="level"> <mx:Array> <mx:Object label="A" data="1" /> <mx:Object label="B" data="2" /> <mx:Object label="C" data="3" /> <mx:Object label="D" data="4" /> </mx:Array> </mx:ComboBox> <mx:TextInput id="selectedLevel" /> </mx:HBox> Notice that we’re not setting the text property of the text input. With curly brace syntax, we’d set the text property inline. With the <mx:Binding> tag we’ll use a sepa- rate tag to achieve the goal of data binding. To link the source ( level.value) and the destination ( selectedLevel.text), you can add the following tag to your code (note that the tag must appear outside of any layout container tags): <mx:Binding source="level.selectedItem.data" destination="selectedLevel.text" /> 272 | Chapter 12: Working with Data This code works identically to how the curly brace example worked, yet it uses a dif- ferent mechanism to achieve that goal. You can use <mx:Binding> with data models and RPC components as well. We can rewrite the earlier data model example to illustrate this point. First, add the data model, the RemoteObject, and the controls. Note that in this example, the data model and the remote method arguments do not define any values inline: <mx:Model id="dataModel"> <userData> <email></email> <phone></phone> <city></city> <state></state> </userData> </mx:Model> <mx:RemoteObject id="example" destination="exampleService"> <mx:method name="saveContactInformation"> <mx:arguments> <email></email> <phone></phone> <city></city> <state></state> </mx:arguments> </mx:method> </mx:RemoteObject> <mx:VBox> <mx:Label text="Email" /> <mx:TextInput id="email" /> <mx:Label text="Phone" /> <mx:TextInput id="phone" /> <mx:Label text="City" /> <mx:TextInput id="city" /> <mx:Label text="State" /> <mx:ComboBox id="state"> <mx:Array> <mx:Object label="CA" /> <mx:Object label="MA" /> </mx:Array> </mx:ComboBox> <mx:TextArea id="summary" width="200" height="200" /> </mx:VBox> Next, we need to define the data bindings using the <mx:Binding> tag: <mx:Binding source="email.text" destination="dataModel.email" /> <mx:Binding source="phone.text" destination="dataModel.phone" /> <mx:Binding source="city.text" destination="dataModel.city" /> <mx:Binding source="state.value" destination="dataModel.state" /> <mx:Binding source="'Contact Information\nEmail: ' + dataModel.email + '\nPhone: ' + dataModel.phone + '\nLocation: ' + dataModel.city + ', ' + dataModel.state" destination="summary.text" /> Data Binding | 273 <mx:Binding source="dataModel.email" destination="example.saveContactInformation.arguments.email" /> <mx:Binding source="dataModel.phone" destination="example.saveContactInformation.arguments.phone" /> <mx:Binding source="dataModel.city" destination="example.saveContactInformation.arguments.city" /> <mx:Binding source="dataModel.state" destination="example.saveContactInformation.arguments.state" /> You can also use E4X expressions with the <mx:Binding> tag. Assume you change the data model from a Model object to an XML object as follows: <mx:XML id="xmlData"> <userData email="{email.text}" phone="{phone.text}" city="{city.text}" state="{state.value}" /> </mx:XML> You can then change the <mx:Binding> tags as follows: <mx:Binding source="email.text" destination="xmlData.@email" /> <mx:Binding source="phone.text" destination="xmlData.@phone" /> <mx:Binding source="city.text" destination="xmlData.@city" /> <mx:Binding source="state.value" destination="xmlData.@state" /> <mx:Binding source="'Contact Information\nEmail: ' + xmlData.@email + '\nPhone: ' + xmlData.@phone + '\nLocation: ' + xmlData.@city + ', ' + xmlData.@state" destination="summary.text" /> <mx:Binding source="xmlData.@email" destination="example.saveContactInformation.arguments.email" /> <mx:Binding source="xmlData.@phone" destination="example.saveContactInformation.arguments.phone" /> <mx:Binding source="xmlData.@city" destination="example.saveContactInformation.arguments.city" /> <mx:Binding source="xmlData.@state" destination="example.saveContactInformation.arguments.state" /> The <mx:Binding> tag requires more code than the curly brace syntax. Curly brace syntax can appear inline within existing tags, whereas <mx:Binding> syntax requires that you add additional tags to your code. This may seem like a disadvantage at first; however, in the long run it is advantageous to use <mx:Binding> in most cases because it allows you to create a cleaner separation between UI layout and the data used. Using the <mx:Binding> tag is a cleaner implementation of data binding, yet it does not allow any greater functionality than curly brace syntax. If you need more functionality (such as dynamically changing data binding end points at runtime) you can use BindingUtils, discussed in the next section. BindingUtils In most cases, you should use curly brace or <mx:Binding> syntax for data binding. However, neither technique allows you to dynamically configure data binding at run- time. The mx.binding.utils.BindingUtils class has a static method called bindProperty( ) that allows you to configure data binding from ActionScript. This ActionScript solution provides the most flexibility and the lowest-level access to data 274 | Chapter 12: Working with Data binding of all the techniques. As such, the BindingUtils.bindProperty( ) method can be a useful resource in those special cases in which you require more flexibility than the other techniques afford you. The syntax for the bindProperty( ) method is as follows: BindingUtils.bindProperty(destinationObject, destinationProperty, sourceObject, sourceProperty); The destination and source object parameters are object references, and the property parameters are strings. The following example links the value from a combo box so that it displays in a text input: BindingUtils.bindProperty(textInput, "text", comboBox, "value"); Because BindingUtils is ActionScript, you can place the code anywhere that you can place ActionScript code. The following example uses a button to enable data bind- ing between a combo box and a text input when the user clicks the button: <mx:Script> <![CDATA[ import mx.binding.utils.BindingUtils; ]]> </mx:Script> <mx:VBox> <mx:ComboBox id="comboBox"> <mx:Array> <mx:Object label="1" /> <mx:Object label="2" /> <mx:Object label="3" /> <mx:Object label="4" /> </mx:Array> </mx:ComboBox> <mx:TextInput id="textInput" /> <mx:Button label="enable data binding" click="BindingUtils.bindProperty(textInput, 'text', comboBox, 'value')" /> </mx:VBox> In the preceding example, the combo box and the text input are not initially linked. However, when the user clicks on the button, it calls the bindProperty( ) method, which links the controls such that the combo box value is displayed in the text input, and the display changes as the value changes. To use BindingUtils, you must add an import statement, as in the example. The bindProperty( ) method returns a reference to a new mx.binding.utils. ChangeWatcher object. The ChangeWatcher class defines a class of objects that repre- sents the actual data binding link between a source and a destination. Using bindProperty( ) by itself allows you to enable data binding at runtime, but if you want to further modify that data binding, you’ll have to work with a ChangeWatcher object. Using a ChangeWatcher object, you can disable data binding or change the source point. Data Binding | 275 The ChangeWatcher object returned by a bindProperty( ) method call represents that data binding association, and if you want to change that association or stop it, you must use the ChangeWatcher object. You can stop a data binding association between two points by calling the unwatch( ) method of the ChangeWatcher object: changeWatcher.unwatch( ); You can retrieve the current source value using the getValue( ) method: changeWatcher.getValue( ); You can change the source object using the reset( ) method. The reset( ) method accepts one parameter specifying the new source object: changeWatcher.reset(newSourceObject); The reset( ) method does not allow you to change the property of the source object. If you want to change the property, you must call unwatch( ) to stop the current data binding association. You can then start a new association using BindingUtils. bindProperty( ) : changeWatcher.unwatch( ); changeWatcher = BindingUtils.bindProperty(newSource, newProperty, destination, destinationProperty); Example 12-2 uses BindingUtils and ChangeWatcher to toggle the source object between two combo boxes. The example uses two combo boxes, a text input, and a button. When the application initializes, it calls the initializeHandler( ) method because that is assigned to the Application initialize handler. The initializeHandler( ) method sets data binding between the level combo box and the selectedLevel text input. When the user clicks the button it calls the toggleDataBinding( ) method, which uses the reset( ) method of the ChangeWatcher object to change the source object. Example 12-2. Working withBindingUtils <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" in itialize="initializeHandler(event)"> <mx:Script> <![CDATA[ import mx.binding.utils.BindingUtils; import mx.binding.utils.ChangeWatcher; private var _changeWatcher:ChangeWatcher; private var _currentHost:ComboBox; private function initializeHandler(event:Event):void { // Set the initial data binding, and assign the ChangeWatcher // object to the _changeWatcher property. _changeWatcher = BindingUtils.bindProperty(selectedLevel, "text", level, "value"); [...]... of a custom class and an instance of the class to use the instance for data binding For instance, consider the simple class in Example 12- 3 Enabling Data Binding for Custom Classes | 27 7 Example 12- 3 Basic data binding class example package com.oreilly.programmingflex.binding { [Bindable] public class DataBindableExample { private var _example:String; public function get example( ):String { return... class declaration Example 12- 5 uses custom event names Example 12- 5 Customized data binding package com.oreilly.programmingflex.binding { import flash.events.Event; import flash.events.EventDispatcher; public class CustomizedDataBindableExample extends EventDisaptcher { private var _a:String; private var _b:String; Enabling Data Binding for Custom Classes | 27 9 Example 12- 5 Customized data binding... 27 8 | Chapter 12: Working with Data Example 12- 4 Implementation of... /> /> data="1.1" data="1 .2" data="1.3" data="1.4" /> /> /> /> 27 6 | Chapter 12: Working with Data Enabling Data Binding for Custom Classes Data binding is enabled... data binding Example 12- 6 Data binding example 28 0 | Chapter 12: Working with Data Example 12- 6 Data binding example (continued) 28 2 | Chapter 12: Working with Data Building Data Binding Proxies | 28 5 29 6... you learned about the basics of working with data You read about using data models, both the Flex framework tag-based data models and the preferred ActionScript class-based data models You also learned about using data binding to link data to components and ensure that the data is always in sync Summary | 28 7 Chapter 13 13 CHAPTER Validating and Formatting Data 13 When working with data, you’ll frequently... _validator.source = sourceObject; _validator.property = "sourceProperty"; Example 13 -2 achieves exactly the same thing as Example 13-1, but in this case, the validator is created using ActionScript Example 13 -2 ActionScript-based validator . 26 6 | Chapter 12: Working with Data Example 12- 1. User class package com.oreilly.programmingflex.data { public class User { private var _nameFirst:String; . { if(userType <= 2) { _userType = userType; } } public function User( ) {} } } Example 12- 1. User class (continued) 26 8 | Chapter 12: Working with Data Data Binding Flex applications typically. value=" ;20 0" minimum=" ;20 0" maximum="400" stepSize="10" height=" ;22 "/> <mx:NumericStepper id="panelHeight" value=" ;20 0"

Ngày đăng: 06/08/2014, 08:22