日期:2010-07-26  浏览次数:20457 次

  Atlas架构提供了一种比ASP.NET中数据绑定(data binding)强大得多的客户端绑定模型。这种模型异常灵活,甚至有些类似WPF(Windows Presentation Foundation)中的绑定模型。Atlas提供的绑定模型允许您将某对象的任意一个属性绑定到另外一个对象的任意一个属性上。它不单单可以应用于数据绑定,甚至可以将某个控件的样式绑定到另外一个控件上。这样使得在Atlas中将一切关联起来变成可能。

  在本文中,我将尝试分析一些Atlas实现代码来解释Atlas是如何完成Binding的。

  首先让我们察看一小段应用Atlas Binding的代码。这里将一个textbox的text属性和一个select list的selectedValue属性绑定起来。无论你改变其中的哪个,在另一个上面都会有立刻得到体现。

  HTML和ASPX,定义textbox和select list。(注意必须声明一个ScriptManager服务器端对象,以引入Atlas必须的JavaScript文件。)

<atlas:ScriptManagerID="ScriptManager1"runat="server"/>
<div>
Inputanintegerfrom1to5.<br/>
<inputid="myTextBox"type="text"/><br/>
Selectanitem.<br/>
<selectid="mySelect">
<optionvalue="1">value1</option>
<optionvalue="2">value2</option>
<optionvalue="3">value3</option>
<optionvalue="4">value4</option>
<optionvalue="5">value5</option>
</select>
</div>

  Atlas脚本,将上面两个HTML控件“升级”成Atlas控件。

<pagexmlns:script="http://schemas.microsoft.com/xml-script/2005">
<references>
</references>
<components>
<textBoxid="myTextBox">
<bindings>
<bindingdataContext="mySelect"dataPath="selectedValue"property="text"direction="InOut"/>
</bindings>
</textBox>
<selectid="mySelect"/>
</components>
</page>

  如上所示,我们只需要书写一小段简单的代码即可实现需要的绑定功能。

  Atlas是如何实现这些的呢?首先,Atlas需要有一种途径来监听绑定控件的绑定属性的变化(除非你不需要Atlas提供的自动绑定功能)。在Atlas.js中定义了一个名为Sys.INotifyPropertyChanged的接口,类似.NET中提供的一样。对象可以实现这个接口以期让别的对象监听到自己的属性值的变化。Atlas中所有组件的基类,Sys.Component,实现了这个接口。Sys.Component同样提供一个方法raisePropertyChanged(propertyName),这个方法应该在每个属性的setter中被调用以发出INotifyPropertyChanged.propertyChanged事件。

  目前为止,我们可以看一下Atlas控件中textbox的具体实现。看看textbox中是如何在相应的HTML事件发出时同样发出propertyChanged事件的。

var_text;
var_changeHandler;

this.get_text=function(){
returnthis.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');
}
}

  可以看到,当text属性改变时,Atlas发出了propertyChanged事件,这就使绑定到这个属性成为可能。

  而后Atlas的绑定模型捕获到了这个事件,再根据binding声明查找出与其相关的目的对象以及相应的属性,并调用这个属性的Setter来实现目的对象属性的变化。

  如果源对象(source object)实现了INotifyPropertyChanged接口,并且改变的属性就是dataPath 中指定的属性,同时direction 设定为In或者InOut,Atlas绑定将通过分析引入(incoming的binding来处理propertyChanged事件(参考下面将要介绍的evaluateIn()方法)。

  类似的,如果目的对象(target object)实现了INotifyPropertyChanged接口,并且改变的属性就是property中指定的属性,同时direction 设定为Out或者InOut,Atlas绑定将通过分析流出(outgoing的binding来处理propertyChanged事件(参考下面将要介绍的evaluateOut()方法)。

  接下来让我们察看binding实现代码中的的公有方法和属性来分析一下Atlas绑定的核心实现。在这里没有必要列出涉及绑定的全部代码,如果您感兴趣,可以用关键词Sys.BindingBase和Sys.Binding 在Atlas.js文件中进行搜索。首先是Sys.BindingBase提供的方法和属性。

  • 属性automatic:指定当源对象的相应属性变化时(对于In和InOut),或者目的对象的相应属性变化时(对于Out和InOut),绑定是否将被自动执行。这个属性默认会被置为true。当然如果你需要完全控制绑定的开始时机时也可以设定为false。例如,某些情况下你决定在一个AJAX请求成功返回的时候才开始绑定数据源与显示控件,以确保显示控件真正绑定到了一些数据,这时你需要显示的调用binding的evaluate()方法以开始绑定。
  • 属性dataContext:指定拥有待绑定属性的对象。如果不指定的话,Atlas binding将调用包含它的父控件的dataContext属性代替。控件可以通过返回设定的dataContext或是按照默认返回其父控件的dataContext来实现这个属性。例如,某个ListView控件可以在其创建ListView Item时设定它的dataContext为一个D