领先技术

ASP.NET AJAX 4.0 中的动态数据绑定

Dino Esposito

最近,我移入新办公室,通过极其惊喜和 gratifying 体验,我有超过 10 年中收集的所有编程书籍向上装箱的原因。

这些书籍可以告诉非常清楚地 Web 编程中在过去十年和哪些技术后跟另一个,每个提高 (以及在 revolutionizing 的很多情况下) 的发展其他。

一本书,特别是发现我关注。 它对于 Internet 资源管理器 4 涵盖 (良好,用于该纪元) 程序的编程技术。 我 couldn’t 抵御通过其页面翻转诱惑。

后期 90 年代进行 Web 和浏览器动态和高度可编程环境其第一个尝试了从事计算机行业中的最大名称。

数据绑定时只是一个许多流行的功能正在研究和开发。 虽然数据绑定的基本思路 hasn’t 了重大更改在年中,久远作为 Web 世界向其应用程序出现了实际的转换。 若要通过 Web 实现数据绑定常见的方法是截然不同今天比后期 90 年代和很多差异是由于异步 JavaScript 和 XML (AJAX)。

此列中我讨论各种形式的客户端的数据绑定,如在 ASP.NET AJAX 4.0 它们即将。 在具体的方式而言,我重点数据绑定和可观察到的对象的某些高级功能。

基本原则

通常来说数据绑定是只需程序已经绑定到数据源中的成员的目标组件的某些成员的能力。 快速应用程序开发 (RAD) 工具 (如 Microsoft Access 和 Microsoft Visual Basic 进行数据绑定成功的现实情况。

RAD 工具提供开发人员将可视元素绑定到数据源中的成员一种便捷而且有效的基础结构。 很长的时间被唯一地标识数据源与记录集数据流源自 SQL 查询。

在这方面数据绑定将很好地适合智能客户端方案中但会带来额外的问题,如果采用在 Web 客户端方案。 渚嬪如何将您流动原点数据库服务器,down to 请求 JavaScript-equipped 的浏览器中的记录?

除了许多其他事项后 oblivion 中的年讨论数据绑定功能的 IE4 打开该旧簿基于几个特殊恰当名为表格式数据控件 (TDC) 和远程数据服务 (RDS) 控件的 ActiveX 组件。 图 1 阐释客户端的数据绑定的总体体系结构,因为它已在动态 Web 纪元的开头预想 IE4 体系结构设计者通过。

图 1 的 客户端数据绑定在 Internet Explorer 4

made-to-measure 的 ActiveX 控件管理与远程数据源连接,并采用护理下载和 (可选) 缓存的数据。 数据源是 RDS 与任何符合 ODBC 数据源 ; 它 ’s 带有 TDC 服务器端文本的文件。

通过浏览器特定 HTML 属性,如 datasrc、 datafld 和 dataformatas 实现实际的绑定源和目标元素之间。 在此处 ’s 快速示例:

<span id="Label1" datasrc="#rdsCustomers" datafld="CompanyName" />

绑定字段的内容 — — 在示例中的公司名称 — 占用 SPAN 标记中得到文档对象模型 (DOM) 为保留的空间。

将数据插入到 DOM 的实际作业些什么? 如上所述,它 ’s 在这种情况下进行这一轮在浏览器。 浏览器在遇到 dataXXX 中的任何属性时它会查询数据源控件为使用内部、 拗 API 的数据。 它获取任何数据然后被插入到最终的 DOM 并向用户显示。

您可以看到该解决方案强烈的浏览器特定于和 understandably 永远不会捕获开发人员的核心。

客户端的数据绑定作为 ASP.NET 的几年然后留出设置和其服务器端编程模型所获得的宽验收。

在最近的几年中的 AJAX 出现生成大量的客户端的数据绑定周围的兴趣和工程师已回处工作查找一个有效 (以及此时间跨浏览器) 方法,使其发生这种情况。

在 ASP.NET AJAX 的演变

图 2 显示客户端的数据绑定的总体体系结构与它在 ASP.NET AJAX 4.0 中实现。

图 2 的 客户端数据绑定在 ASP.NET AJAX 4.0

尽管 图 1 中属体系结构,并 的 图 2 可能类似一眼,但它们实际上不同数关键方面。

首先,并将 foremost,您可以与 ASP.NET AJAX 4.0 生成工作与任何现代的浏览器的客户端的数据绑定解决方案。 实际绑定到目标元素的源数据所需的粘附代码现在是 Microsoft Ajax JavaScript 库的一部分。 为这样它可以在任何浏览器中承载。

此外,为绑定您不再具有如 datasrc 和浏览器必须解析 datafld 的专有和非标准 HTML 属性。 而是,绑定信息是使用指定符合 XHTML 标准,namespaced JavaScript 库中的代码被解析的自定义属性。 它也可以执行强制。

旧样式与新建样式

另一个重大的区别在于数据源对象的结构。 旧式数据绑定中使用管理您的数据检索的黑色框代理的排序。 在 ASP.NET AJAX 4.0,don’t 需要这样 ActiveX 或二进制的组件。 您所需要的全部工作就是与源数据的 JavaScript 对象。

内置绑定基础结构的链接在一起字段 JavaScript 源对象和该 DOM.中的元素上

在 ASP.NET AJAX 4.0,Sys.UI.DataView 组件内置这样的绑定基础结构。 从功能上对说话 DataView 对象操作方式大致相同,IE4 样式客户端数据绑定 RDS 控件一样。 它直接连接到一个远程终结点获取和公开数据。

但是,有一些差异。 DataView 对象是完全编写的 JavaScript 要求任何特殊支持从运行浏览器客户端控件。 您可以看到 ’s 从 RDS ActiveX 控件完全不同。

此外,DataView 控件 doesn’t 直接与关系数据源接口。 它所连接到任何 JavaScript 对象表示法 (JSON) 相反,-或带边距 JSONP 的 JSON 启用服务如 Windows 通信基础端点和使用 JSON 交换数据。 服务可以换行 (包括一个关系数据库) 任何物理数据存储区或甚至是普通的包装实体框架模型。 如图 2 所示,在 ASP.NET AJAX 4.0 甚至可以在不使用出站网络连接到服务器的位置具有数据绑定。 如果说,时加载,页下载到客户端计算机上的某些数据您可以在没有任何进一步的往返,到服务器的本地缓存数据上的工作有数据绑定。

Brief 摘要

在剪切边缘列 ( msdn.microsoft.com/magazine/ee309508.aspx ) 的十月 2009年分期付款,我涵盖从开发人员已经视角的 ASP.NET AJAX 4.0 中的数据绑定的基础知识。 虽然您仍可以参考深覆盖率该文章,我将在此处提供的最重要的编程事实数据,为客户端数据绑定的简短摘要。

在 ASP.NET AJAX 4.0,客户端的数据绑定可发生在适当的 HTML 模板内。 模板是一个用 sys 模板 CSS 属性修饰的 DOM 树:

<div sys:attach="dataview1" class="sys-template">  
   ...
</div>

sys 模板是一个用户定义的 CSS 样式中包括下列在非常小的常规名称:

<style type="text/css">
   .sys-template { display:none; }
</style>

修饰 sys 模板属性具有一个给定的 HTML 标记不够,但是。 您还必须添加一些行为以使它可以处理任何绑定表达式内的标记。 在此上下文中一个行为是只需 made-to-measure JavaScript 组件或控件的实例。

通过实例化行为以编程方式或通过使用声明性的方法 (通过将标记添加到模板标记页中),可以将一个行为附加到 HTML 标记。 声明性的方法的行为必须与公用名称 (命名空间前缀) 相关联。

在此处 ’s DataView 组件的实例分配一个公用名称的示例:

<body xmlns:sys="javascript:Sys" 
      xmlns:dataview1="javascript:Sys.UI.DataView">
...
</body>

在 sys: 附加属性获取公用名称,然后创建引用的行为对象的实例。 在第一个在本节中的代码示例,DIV 标记能够具有由名为 dataview1 对象来表示的行为。 您可以猜出,dataview1 是 Sys.UI.DataView JavaScript 对象中的,只是公用名。

一旦 DataView 实例已附加到 ASP.NET AJAX 4.0 模板,该 DataView 可以成功地处理在模板中包含任何绑定表达式。 在此处 ’s 与最简单的绑定语法示例模板:

<ul id="imageListView" class="sys-template" 
     sys:attach="dataview1" 
    dataview1:data="{{ imageArray }}">
    <li>
        <span>{{ Name }}</span>
        <span>{{ Description }}</span>
    </li>
</ul>

{{表达式}} 令牌告诉 DataView 处理嵌入的 JavaScript 表达式,并将结果赋给 DOM 或指定的 DataView 属性。 渚嬪以上代码将分配一个名为到 DataView 属性名为数据 imageArray 的 JavaScript 变量的内容。 此方法中定义数据源的绑定操作。 此信息用于展开模板如上面使用正文中的两个 SPAN 标记内的任何其他绑定表达式。 名称和说明应为公共属性上的数据项目或项目分配给该 DataView 的数据属性中。

内联表达式求值

{{表达式}} 语法表明最简单的绑定支持 ASP.NET AJAX 4.0 的类型。 仅当呈现模板计算这种方式来表示任何绑定。 它们是永远不会更新的除非以编程方式刷新该模板。

内联表达式对照数据源的当前状态评估在呈现时,但是 doesn’t 自动捕获到数据源所做的任何进一步的更改。

可选的、 更丰富的绑定模型还支持,为您提供了相同的编程电源的 XAML 数据绑定 Windows 演示基础和 Silverlight 的应用程序中。 高级数据绑定功能的类集通常被称为 居住绑定 。 let’s 找到更多信息。

实时绑定

实时绑定可确保在用户界面中显示的值将自动更新绑定的值在数据源发生更改的任何时间。 渚嬪假设建立 SPAN 标记和公司名称属性中的数据源之间实时绑定。 SPAN 标记显示在呈现时的公司名称属性的当前值。 但是,SPAN 标记的内容将被自动更新绑定的数据源属性所经历的更改的任何时间。 实时绑定可应用于任何的两个对象是否 DOM 元素或 JavaScript 对象。

不同的语法是必需的实时绑定表达式。 例如:

<span>{binding CompanyName}</span>

若要自动换行在表达式中使用一对大括号和前缀与关键字绑定。 您可以看到总体的语法包含很多与此等效的 XAML 语法和的 isn’t 巧合。

应该注意每当在当前绑定的数据项上检测到更改时,更新 SPAN 标记前面显示的内容 ; 相反 won’t 工作。 如果更新在 SPAN 内容,won’t 的更改传播到源对象。

实时绑定还可描述作为时检测到数据源上的更新,可能反复发生一个单向绑定。

持有上! 检测到绑定上的更改所采用的策略是一个关键点和有更多有关其说,在某个时刻,但不是先引入双向绑定。

鍙屽悜数据绑定

双向数据绑定是一种特殊形式的以检测更改绑定上的使用两个通道的实时绑定。 双向绑定时在两个对象之间的位置发生以下情况:

  • 如果数据源更改,自动刷新目标对象。
  • 如果将更改目标对象新的状态将被传播到基础数据源。

放入另一种方法,双向数据绑定可以确保源和目标对象始终保持同步。

没有层交叉

下列可能您可能听起来像 foregone 结论但让我清除仍要进行。 假设您有一个的用户界面和服务从数据库中检索到的某些数据之间的双向绑定。

数据从服务器下载和绑定到用户界面的可视元素表示域模型的快照。 渚嬪说它代表一个客户的对象。 如果显示的客户对象修改双向绑定页中,然后客户端的客户对象的镜像卷检测到的所有更改,但没有方法中将它们传播到服务器。 双向数据绑定 doesn’t 跨越任何层。

在语法,方面双向绑定是单向的实时绑定几乎相同。

ASP.NET AJAX 绑定通过 Sys.Binding JavaScript 对象表示。 您可以控制通过 mode 属性,该框架为您使用实时绑定语法任何时间创建 Sys.Binding 对象上的数据流的方向。 (请注意没有 Sys.Binding 对象创建时为纯 {...} 可选内联表达式。

下面的代码段显示了如何设置双向数据绑定使用 mode 属性:

<span id="Label1">{binding CompanyName, mode=twoWay}></span>

在的图 3 中汇总了 mode 属性的可能值。

成员 说明
自动 0 如果目标是输入的元素、 选择的元素、 textArea 元素或实现 Sys.INotifyPropertyChange 界面的组件,数据流是 twoWay。 数据流否则是单向。
oneTime 1 数据传输来自源对象到目标仅一次呈现该模板时。
单向 2 每次更新源时,数据是来自源对象传输到目标中。
twoWay 3 数据传输到目标更新源时, 从源对象并从目标到源每当更新目标。
oneWaytoSource 4 每当更新目标时,数据将从目标转移到源中。

图 3 的 Sys.BindingMode 枚举

居住在操作中的绑定

图 4 显示了代码示例演示了实时、 双向数据绑定。 该页包含一个使用 DataView 控件呈现的模板。 数据源对象是一个名为 theCustomers 的 JavaScript 数组。 通过该 theCustomers 是一个静态定义的客户端浏览器中的本地对象的事实被 fooled don’t。 是真正关键的问题是该 theCustomers 最终会分配到 DataView 对象的数据属性。 DataView 对象具有丰富的编程接口,使您得以将包括从 Web 服务下载的内容的任何内容放入数据属性。

<asp:Content ID="Content2" runat="server" ContentPlaceHolderID="PH_Head">
  
    <link rel="stylesheet" type="text/css" 
      href="../../Css/lessantique.css" />
    <style type="text/css">
        .sys-template { display:none; }
    </style>
    
    <script type="text/javascript">
        var theCustomers = [
           { ID: "ALFKI", CompanyName: 
            "Alfred Futterkiste" },
           { ID: "CONTS", CompanyName: 
           "Contoso" }
        ];
    </script>
</asp:Content>    

<asp:Content ID="Content5" 
  ContentPlaceHolderID="PH_Body" 
  runat="server">

    <asp:ScriptManagerProxy  
    runat="server">
        <Scripts>
          <asp:ScriptReference Path=
"https://ajax.microsoft.com/ajax/beta/0910/MicrosoftAjaxTemplates.js" />
        </Scripts>
    </asp:ScriptManagerProxy>

    <div id="customerList">
       <ul class="sys-template" 
         sys:attach="dataview" dataview:data="{{ theCustomers }}">
         <li>
           <span><b>{binding ID}</b></span>
           <input type="text" id="TextBox1" 
             value="{binding CompanyName}" /> 
           <br />  
           <span>Currently displaying... 
<b>{binding CompanyName}</b></span>  
         </li>
       </ul>
    </div>
</asp:Content>

图 4 Live 双向绑定示例

为每个绑定的数据项模板会发出一个 LI 标记包含一个文本框。 文本框是绑定到源的公司名称属性。 在同一模板 SPAN 标记也绑定到源的公司名称属性。

请注意实时绑定不限于它们属于该模板。 您可以有相同的表达式 — 说,{绑定公司名称} — 在两个不同的模板中。 对这两个模板中附加相同的数据源对象 (或兼容的对象),只要该绑定将始终得到正确解析。 图 5 显示了运行中的页面。

图 5 Live 绑定在操作

最初文本框和 SPAN 标记包含相同的数据。 然而,在某些时候用户可能开始编辑文字框中公司的名称。 直到出文本框的用户选项卡没有任何反应。

在文本框失去焦点时,编辑阶段被视为完整。 在这时双向数据绑定机制触发,并更新基础数据源对象。 因为 SPAN 标记也绑定到相同的数据属性,通过实时绑定,任何更改将传播。

若要防止数据源的自动更新涉及 INPUT 元素时,您模式属性显式设置,作为下面所示:

<input type="text" value="{binding CompanyName, mode=oneWay}" />

图 4 中代码输入此更改并查看不同之处。

正在检测更改

当一个绑定的 mode 属性未显式设置时,花费 auto 值 的 图 3 所述。 因此当一个绑定到任何输入方案 (如 INPUT、 SELECT 或 TEXTAREA),请参阅的 HTML 元素,属性模式默认 twoWay。 鍥犳目标通过浏览器已经用户界面所做的所有更改将自动都转移到源。

请注意有两种形式的单向绑定。 标准单向绑定源中检测到更改,并反映它们在用户界面中。 备用 oneWayToSource 执行相反的操作:它在目标中检测到更改,并反映它们在源对象中。 请尝试使用下面的代码:

<input type="text" value="{binding CompanyName, mode=oneWayToSource}" />

初始页面的显示将包含空的文本框。 当您键入,但是,新文本检测到,并处理按预期的方式。

双向数据绑定选项也是用于任何绑定的 JavaScript 对象发生了实现 Sys.INotifyPropertyChange 接口的默认选项。 (接口是 Microsoft Ajax JavaScript 库的一部分。

当我首次引入实时绑定时,我说源发生更改时,更新目标。 以下说明框架可以检测哪些更改和方式。

HTML 输入的元素激发时更改其状态,或一个至少它们时通知他们进入或退出编辑阶段的标准事件。 因为这些事件是 HTML 标准的一部分,根据该标准的任何数据绑定解决方案将工作在任何浏览器中。

获得的绑定来反映在另一侧更新它已完成在一种方法就是可能检测到。 假设您有一个绑定源位置是一个 JavaScript 数组如下所示:

<ul class="sys-template" sys:attach="dataview" 
    dataview:data="{{ theCustomers }}">
  <li>
     <span ><b>{binding CompanyName}</b></span>
  </li>
</ul>

试图更新该数组内的对象中的公司名称属性。 标记显示一个按钮是否单击了运行 enterChanges JavaScript 工作,显示此处:

<span>{binding CompanyName}</span>
<input type="button" value="Enter changes" 
onclick="enterChanges()" />
...
<script type="text/javascript">
    function enterChanges() {
        theCustomers[0].CompanyName = 
       "This is a new name";
    }
</script>

enterChanges 函数更新数组中第一个对象上的公司名称属性。 正如您看到这显然是对象的更新绑定的状态的操作。

在实时绑定的情况下,您有望 SPAN 标记以显示新值。 如果您尝试的但是,您将看到没有任何反应。

这是因为没有跨浏览器的方法,如普通的旧 JavaScript 对象发生的更新的通知。 因此更改发生这种情况,但绑定 isn’t 知道的和 isn’t 刷新用户界面。

将轮询普通的 JavaScript 对象的状态是可行的解决方案吗? 可能不和开发团队合理行宽出该选项,实质上是出于可伸缩性方面的考虑。

在该结束使用输入的 HTML 元素绑定到数据仅有可能导致使数据更改的成功地将触发其他实时的绑定方式吗? 嗯,不完全。 Microsoft Ajax JavaScript 库提供了一个静态的 API,通过它可以"观察"任何 JavaScript 对象的更改。 此 API 也是一个普通的 JavaScript 对象转换为一个可观察到的对象,用于检测更新绑定机械口味中可用的。

可观察到的 JavaScript 对象

可观察到的 JavaScript 对象是 endowed 引发的附加功能与对象更改时修改的通知。 附加功能 codified 通过 Sys.Observer 界面。 请注意,而不需要通过该接口的直接,所做的更改不会引发更改通知,并由绑定基础结构将被忽略。

可观察到的对象完全适合您要建立可视元素,如您可能会收到来自远程的 Web 服务的 JavaScript 对象之间的实时绑定的方案。

有两种方法来处理可观察到的对象。 其中一个需要通过向它添加一些动态代码使给定的对象才能看见 — 不足以使普通的 JavaScript 对象是复杂的事情但足够添加新的功能。 这里是一个示例:

<script type="text/javascript">
    var theCustomers = [
            { ID: "ALFKI", CompanyName: 
            "Alfred Futterkiste" },
            { ID: "CONTS", CompanyName: 
            "Contoso" }
        ];    
    function pageLoad() {
        Sys.Observer.makeObservable(theCustomers);
    }
    
    function onInsert() {
        var newCustomer = { ID: "ANYNA", 
        CompanyName: "AnyNameThatWorks Inc" };
        theCustomers.add(newCustomer);
    }
</script>

Sys.Observer.makeObservable 方法采用 (包括数组) 的 JavaScript 对象,并将方法添加到它您可以使用绑定可以检测到的对象进行更改。 请注意具有可观察到的数组提供了可观察到的方式更改数组的方法 — — 以便插入和删除可以检测到。 但它不会自动提供相应的方法的可观察到的方式修改该数组中各个项的属性。 为该,可以分别在各个项上调用 makeObservable 和它们然后还可以添加的其他方法。

 如我上文下面的代码与单击事件相关联 won’t 触发绑定:

<script type="text/javascript">
    function enterChanges() {
        theCustomers[0].CompanyName = 
        "This is a new name";
    }
</script>

但是,此代码将触发该绑定:

<script type="text/javascript">
    function enterChanges() {
       System.Observer.setValue(theCustomers[0], 
       "CompanyName", "New name");
    }
</script>

如果观察到的对象有子对象吗? 没有 worries 中:setValue 方法知道如何处理"虚线"语法:

System.Observer.setValue(theCustomers[0], "Company.Address.City", "Rome");

最后,注意观察器模式可应用于包括 DOM 元素、 行为和甚至浏览器对象 (如窗口的 Web 页的上下文中,您可能会遇到的任何对象。

静态和动态

大多数时间需要在应用程序中的数据绑定时,您还需要它是实时、 至少单向如果不是双向。在 ASP.NET AJAX 4.0,数据绑定可以是两个静态 — 也就是一个简单的内嵌的评估数据值呈现过程中) 和动态,在这个意义上,它可以检测源或目标中的更改并应用的 them.Not 检测到并绑定,刷新所有更新。ASP.NET AJAX 4.0 很容易地识别输入到通过可视元素的绑定对象的更改。但是,对于以编程方式输入到 JavaScript 对象或数组的更改 ’s 不可靠的跨浏览器方法有实时检测的更改。在 ASP.NET AJAX 一轮牌组成,提供一种方法,以便它们 ’re 才能看见,因此可以被检测到实时绑定进行更改。转到该对象,或作为使用特别 Sys.Observer 静态方法进行更新的替代方法将追加可观察到的某些操作的窗体。

Dino Esposito* 的作者在即将开始 “ 编程 ASP.NET MVC 2 ” (微软出版社,2010年) 是基于在意大利,Esposito 是频繁的演讲者在全球范围内的行业事件。您可以在 weblogs.asp.net/despos 加入他的博客。*

感谢到下面的技术专家审阅此文章: Dave Reed 和 Boris Rivers-Moore