Atlas Unleashed - Bindings
Dflying | 04 April, 2006 00:37Atlas provides a binding model which is much more powerful than the data-binding model in ASP.NET. It is quite a flexible binding mechanism; just something like the binding models in WPF (Windows Presentation Foundation).Atlas binding lets you bind any property of one component to any property of another object. It may connect everything in Atlas. Therefore we call them bindings, not only the data-bindings, for we can even bind the style of one control to a property of another control.
In this post, I will try to explain what is inside this and how Atlas makes this work by zooming in the Atlas framework code.
Let's take a look at a small piece of Atlas binding code which binds the text property of a textbox to the selectedValue property of a select list. When updating one of the two controls, we want the other one get updated accordingly too.
HTML and ASPX, defines a text box and select list.
<atlas:ScriptManager ID="ScriptManager1" runat="server" />
<div>
Input an integer from 1 to 5.<br />
<input id="myTextBox" type="text" /><br />
Select an item.<br />
<select id="mySelect">
<option value="1">value 1</option>
<option value="2">value 2</option>
<option value="3">value 3</option>
<option value="4">value 4</option>
<option value="5">value 5</option>
</select>
</div>
Atlas Page Script, upgrades the two HTML controls to Atlas controls, and sets up the two ways binding.
<page xmlns:script="http://schemas.microsoft.com/xml-script/2005"> <references> </references> <components> <textBox id="myTextBox"> <bindings> <binding dataContext="mySelect" dataPath="selectedValue" property="text" direction="InOut" /> </bindings> </textBox> <select id="mySelect" /> </components> </page>
The code we have to write is just simple and it works perfectly.
So, what does Atlas do to make this possible? First of all, Atlas needs a way to listen to property value changes event of its binding controls (unless you don't need the automatic bindings). There is a Sys.INotifyPropertyChanged interface, which is similar to the one provided by .NET, defined in file Atlas.js. Objects can implement this interface to let other objects listen to its property value changes event. The Atlas component class (Sys.Component) implements this interface and all the Atlas controls inherit here. Additionally, the component class has a function raisePropertyChanged(propertyName) which should be called in every property's setters, to raise the INotifyPropertyChanged.propertyChanged event.
OK for now. With this knowledge, we can take a look at a few parts of the TextBox implementation to get the details about how Atlas raises the propertyChanged event when an event of the HTML element was raised.
var _text; var _changeHandler; this.get_text = function() { return this.element.value; } this.set_text = function(value) { if (this.element.value != value) { this.element.value = value; this.raisePropertyChanged('text'); } } this.initialize = function() { Sys.UI.TextBox.callBaseMethod(this, 'initialize'); _text = this.element.value; _changeHandler = Function.createDelegate(this, this._onChanged); this.element.attachEvent('onchange', _changeHandler); _keyPressHandler = Function.createDelegate(this, this._onKeyPress); this.element.attachEvent('onkeypress', _keyPressHandler); } this._onChanged = function() { if (this.element.value != _text) { _text = this.element.value; this.raisePropertyChanged('text'); } }
As we can see, Atlas raises the propertyChanged event whenever the text changes. This makes it possible to actually bind against this property.
When we create a binding, the binding will look at both the source object (where data is from) and the target object (where the data is applying to) to see if it implements INotifyPropertyChanged.
If the source object implements INotifyPropertyChanged, Atlas binding will handle its propertyChanged event by evaluating the incoming binding (see evaluateIn() method later), if the property you specified in the dataPath was the property that changed and the direction is set to In or InOut.
Similarly, if the target object implements INotifyPropertyChanged, its propertyChanged event will be handled by evaluating the 'outgoing' binding (see evaluateOut() method later), if it is the property you defined on the binding and if the direction is set to Out or InOut.
Now we have to be closer to the Atlas binding core implementation. Look at the public properties and methods of a binding, and see what they are used for. It’s in the describer of Sys.BindingBase in Atlas.js. Here I’d better not copy and paste such a long piece of code. If you are interested in the details implementation, just search the Atlas.js file with the keyword Sys.BindingBase and Sys.Binding.
- Property automatic: Specifies whether the binding should automatically be evaluated if the property of the source object's property was changed (In, InOut), or the target object's property was changed (Out, InOut). This property is se t to true by default but it can be also set to false if you want to take full control of when the binding should be evaluated. For example, you only want to evaluate a binding when some AJAX request is completed so it actually has data for binding. You can do this by setting the automatic property to false, and explicitly invoke the evaluateIn() method of the binding as you wish.
- Property dataContext: Specifies the source object which has a property that you want to bind to. You can set this to another object, or if you do not set this property, the binding will call its owner's (parent's) dataContext property by default. Controls implement this property by either returning the dataContext that was set, or by returning its parent control's dataContext. The ListView control can set the dataContext to, for example a DataRow object when it creates ListView items, which makes it possible to bind against data items.
- Property dataPath: The source object's property that you want to bind to. You can bind against nested properties as well by using the following syntax: sourceObjectProperty.nestedProperty.nestedNestedProperty Atlas will transfer and run code for you automatically. The default value is empty, which means Atlas will bind to the source object itself.
- Property property: The target object's property that you want to bind to. You should always set this property to ensure the binding will do something.
- Property propertyKey: Sometimes you may want to bind to a nested property of one object. For example, you may want to bind to the style's property color. You can do so by setting the property property to style, and set the property propertyKey to color.
- Property transformerArgument: argument to be passed to a transformer.
- Event transform: This event lets you apply a transformation during the evaluation of a binding. This can be useful if you want to display a bound value differently in the target object. For example, if you want to show the Boolean value of the data source as Yes/No instead of the default true/false, you may use a transformer. There are several built-in transformers in Atlas, such as Add, Multiply and Compare.
- Method evaluateIn: Evaluates the incoming binding, if the direction was set to In or InOut. It will gett the value of the source object's property (based on the dataContext and dataPath values), and pass this value to the target object property's setter.
Still, here is some useful information in Sys.Binding, also in Atas.js.
- Property direction: Specifies the change directions you want to listen to. Can be set to In, Out or InOut. The default value is In.
- Method evaluateOut: Similar to evaluateIn, but works the other way round, and only works when the direction is set to Out or InOut of course.
Hope the explanation above can bring you a clearer view of how the 'magic' Atlas binding works. Leave your ideas by commenting down.
Posted in
Atlas.
Comment: (2).
Trackbacks:(403).
Permalink
«Next post |
Previous post»
Referers
Comments
-
1. volcanodeng | 04/04,2006 at 17:58
Yes,it is indeed very cool model, and I must start to learn it!
-
2. Dflying | 04/04,2006 at 18:18
Just enjoy :)




