|
|
||||||||||||
| Ultrashock Tutorials > Flash MX 2004 > Data Binding | ||||||||||||
|
||||||||||||
|
|
Data Binding |
|
||||||||||
In the beginning...In the beginning God created the heavens and the Earth. Now the Earth was formless and ark, so God created Flash and he saw that it was good. That was the first day. By the fourth day, God was sick of just plain old animation, so he introduced ActionScript. Day 5 God basically scrapped the old ActionScript and started again, but made it a bit more standards compliant. On the sixth day, it got a revamp and God created a component to inhabit the land. Then God saw that the component was lonely and so he created FireFly, through which components may be bound together and share all the joys of data integration. On the seventh day, God was going to rest but instead made Flash even better by fully integrating Data Binding into the authoring environment and sprucing up the component architecture. So, what is Data Binding?As you probably picked up, Data Binding is not new to Flash, but it has been greatly improved since it was an add-on to Flash MX. Put simply, Data Binding is an easy way to tie all your data together, without any hard work. You can match up properties of different user interface components or even link them to the data on your server via the Data components. Data Binding takes away the need to understand complex ActionScript or how to manipulate XML and reduces it to simple clicks. Data Binding is a key feature of RAD (Rapid Application Development) and is a great tool for prototyping. The point-and-click Data Binding actually works by utilising a runtime Data Binding API. You can access this with your scripts too, provided that you include the required assets in your movie. This just involves copying the Data Binding Classes symbol from the Classes common library, which can be found in the Flash menu bar in Window -> Other Panels -> Common Libraries -> Classes . This is the best approach if you need to build binding into dynamically attached content or if you just like to work in code. However, I will be focusing on the visual interface. Before we begin, grab the source files here and unzip them into a new directory. Finding your bearingsTo start off, let's look at the new panels, that are used for Data binding. They are a bit scary at first, but we'll soon fix that. I have placed them in order of scariness, starting with the Components Panel and ending with the Schema tab in the Components Inspector. Don't freak out just yet.
BasicsSo, since the Components Panel is the least scary, let's start there. We're going to create a very simple binding between two CheckBoxes, like this: (CheckBoxes.fla) Click either of the checkBoxes and you will see that the other changes to reflect the same change. Here's how we're going to do it.
Ok, so that was nice, but not exactly something you've been desperate to be able to do. And there's one panel we haven't looked at yet. The scariest one of all, the Schema Tab. The schema of a component is just an outline of how its data is structured. In the case of a CheckBox, this is very simple; by default it's just a single property, which determines whether it is selected or not. You will see that "selected" is listed in there for the checkBoxes we created just now. SchemaUsing the schema panel, we don't have to be limited to defaults. We can add new properties here and they will become available to be bound to. Often this won't do much because the property won't mean anything, but you can actually set up most component properties for binding. As another simple example, we are going to bind the same checkBoxes together, but this time bind the selected property of one to the enabled property of the other. See the result here. (CheckBoxes_enabled.fla) Notice that checking and un-checking checkBox1 enables and disables checkBox2. This is getting more useful. You can use this to enable or disable parts of a form according to the user's choices. Here's how we do it.
Is everything based on XML these days?Yes! So get used to it - or perish! But XML doesn't have to be difficult with Data Binding. Next we are going to import an XML schema and then populate a Menu Bar from an external XML file, using the XMLConnector component. The first thing you should know about the MenuBar component, in fact many of the XML-driven components (Menu, MenuBar, Tree), is that the names of the XML nodes are ignored. Only the attributes are used. Here is what the XML looks like: <menu>
<menu-title label="file">
<menu-item label="load" />
<menu-item label="save" />
<menu-item label="print" />
</menu-title>
<menu-title label="edit">
<menu-item label="cut" />
<menu-item label="copy" />
<menu-item label="paste" />
<menu-item label="sub-menu">
<menu-item label="nothing here" />
</menu-item>
</menu-title>
</menu>
(xmlMenu.fla) This is where the Schema Panel really comes into its own. We are going to load the data with the XMLConnector component, but use a schema to tell the menu which part of the XML to use.
Arrays and IndexingNow, a huge part of DataBinding is to do with arrays, which are used for populating list-based components such as List, DataGrid or ComboBox. As I mentioned, Flash detects repeated nodes in an XML schema and treats these as an array. To demonstrate how this works, we are going to build a simple little application, which displays a housework rota.
And here is the XML that drives it. So, where to begin? First of all let's import our XML schema. Drop an XMLConnector on stage and import the file "chores2.xml" - make sure that you import it to the results parameter and not params . Next we are going to bind the data to the comboBox, since that is what drives the application. Notice that the XML attribute that stores the days of the week is "label". That's for convenience because that is what the comboBox expects, but normally it isn't best practice. We will look at how to use more appropriate names in the next section on Formatters. To bind the comboBox's dataprovider to the XML source:
Next, we need to tie together the dataGrid and the XML. This is a bit more complicated because the whole dataProvider needs to change whenever a different day is chosen from the comboBox. If you look at the XML and how Flash has interpreted the schema, you will see that it is structured as nested arrays. Each day in the array of days contains an array of jobs. Since everything is only mentioned once in the schema, our next step is to use the schema to bind to the job array inside the nth day. You should be able to do this by yourself now; bind the dataGrid's dataProvider with the job array node in the XMLConnector's schema. But so far we haven't said which job array to bind to - in the actual XML file, there are seven to choose from - we only bound it to the nth day, whatever that is. But Flash has a little secret for determining the value of n.
FormattersOk, so we know how to get a value from one component and put it in another. But that's not always enough. Sometimes we need the data from one component to be displayed differently in another. Other times two components have incompatible data. We tackle this using Formatters. There are several built-in formatters you can choose from, and you can also define your own using an ActionScript 2.0 class. You choose a formatter by selecting a binding and then choosing from the list. Choose Custom Formatter to use your own class.
We'll start with the built-in ones, which are: BooleanPerhaps the simplest of the built-in formatters. It simply takes a Boolean value (true or false) and outputs a string. You can choose what value is represented by true and false in the formatter's options. (Bool_formatter.fla) Compose String Converts fields of an object into a single string. You can combine any number of fields as well as inserting other characters. To create the string template, choose formatter options and type the string in. You can put any text in there, but anything in <> will be treated as a field. If the object has child objects (eg XML) then you can use them too by targeting them with ".". The string template for the example below looks like this: "<last>, <first> (<middle>)" . (Compose_formatter.fla) Date Converts a Date to a String, using a simple template, such as "MM/DD/YYYY" . The allowed tokens are "M" (month), "D" (date), "Y" (year), "H" (hours), "N" (minutes) and "S" (seconds). You can use the formatter in reverse to turn a formatted string into a Date but, for some reason, this only works if you make the binding two-way. (Date_formatter.fla) Number Very simple formatter. Let's you set the number of decimal places to display. (In this case 2dp) (Number_formatter.fla) Rearrange Fields Lets you match up fields in one component's dataProvider with fields named differently in another component. Fields are paired up by listing them in the formatter options as a single string like this: "label=name;data=colour;otherField=yetAnotherField" . This is useful for doing things such as displaying data in a comboBox or List; instead of changing the labelField property of the component, you can just use a rearrange fields formatter to make the field you want appear as the label. In this example, some XML is being loaded and used to populate the comboBox and the fields are rearranged so that the name attribute is used for the label. (Rearrange_formatter.fla) Custom Formatter To make a custom formatter, you need to define a very simple class. All it has are two methods, format and unformat , which take on argument of any type, and may return anything. In this example, the class formats a number into pounds sterling.
// class used to convert numbers to sterling currency and back again
class SterlingFormatter {
// turns a number into a string
function format (data:Number) : String{
var currency:String;
var pounds:Number = Math.floor(data);
var pence:Number = Math.round((data - pounds)*100);
var poundsStr:String = String(pounds);
var penceStr:String;
if(pence<10){
penceStr = "0" + String(pence);
}else{
penceStr = String(pence);
}
currency = "£" + pounds + "." + penceStr;
return currency;
}
// removes sterling format and returns a number
function unformat (data:String) : Number {
var str:String = data.substr(1);
var num:Number = parseFloat(str);
return num;
}
}
Limitations, Precautions and Practices
|
| - discuss this tutorial - |