Welcome 微信登录

首页 / 网页编程 / ASP.NET / 深入ASP.NET数据绑定(中)——数据双向绑定机理

深入ASP.NET数据绑定(中)——数据双向绑定机理2011-08-03 博客园 阿不在上一篇《深入ASP.NET数据绑定(上)》中,我们分析了在.NET中的数据绑定语法的一些内部机理。 简单说来就是ASP.NET在运行时为我们完成了页面的动态编译,并解析页面的各种服务器端代码,包括数 据绑定语法。而数据绑定的语法虽是一些<%# %>代码块,在生成的代码中,仍然使用了服务器端控 件以及在DataBinding事件调用DataBinder.Eval方法来完成数据的绑定工作。所有的数据绑定模板控件都 使用了这样的机制来进行数据的单向绑定,在.NET 2.0中新增了双向的数据绑定方式,主要用在 GridView,DetailsView,FormView等数据容器控件中,结合DataSourceControl就可以非常轻松的完成数据 的更新和提交工作,而不需要我们手工去遍历输入控件的值。那在这样的双向数据绑定中,ASP.NET又是 做了哪些工作,来为我们透明输入控件与字段的取值与对应关系,让我们可以在DataSouceControl中方便 得到数据项修改前的值和修改后的值?下面就让我们一起来从一段页面代码开始吧:

1: <asp:DetailsDataSouce ID="DetailsDataSouce1" runat="server">
2: </asp:DetailsDataSouce>
3: <asp:DetailsView ID="detailsView" runat="server" DefaultMode="Edit" DataSourceID="DetailsDataSouce1">
4: <Fields>
5: <asp:TemplateField>
6: <HeaderTemplate>
7: 电 流:</HeaderTemplate>
8: <EditItemTemplate>
9: <asp:TextBox ID="textBox1" runat="server" Text="<%# Bind ("[电流{a}]") %>"></asp:TextBox>
10: </EditItemTemplate>
11: </asp:TemplateField>
12: </Fields>
13: </asp:DetailsView>

在一个页面中,定义了如上的一个DetailsView控件,为这个控件指定了ID为DetailsDataSource1的 DataSouceControl控件,这个控件是我们自己定义的一个DataSourceControl,它返回的数据字段包 括:"ID","电流{a}","电压(v)","备注"","名称]"。我并没有设置DetailsView的AutoGenerateRows 属性的值,默认情况下,它是为我们自动的生成这些字段的对应的数据显示和输入控件。除此之外,我们 还另外添加了一个数据模板字段,在这个模板中指定了编辑模板。在编辑模板中我使用了<%# Bind ("")%>这样的语法,将textBox1与"[电流{a}]"字段双向绑定起来。

为什么这里的字段都有一些特殊呢?因为我原先的意图是除了分析绑定语法以外,还要测试哪些特殊 字符无法使用数据绑定语法来绑定数据的。这个在下篇文章中会具体介绍。

Bind与Eval不一样,这样的Bind并不Page或TemplateControl的一个方法,事实上我们应该把它当成一 个关键字来看待,因为在ASP.NET的双向数据绑定当中,并没有这样的一个函数存在,它的存在是只是告 诉ASP.NET动态编译页面类时,将这个语法编译成一定的代码格式,并生成一些函数代理来达到双向数据 交流的目的。

那么这一段代码,动态编译生成的服务器代码又是如何的呢?让我们反编译动态程序集,里面会找到 用于创建DetailsView的__BuildControldetailsView的私有方法,在这里会调用到一些其它内部方法,我 们不要让这些方法来干扰我们的视线,直接找到创建如上模板字段的方法:

1: [DebuggerNonUserCode]
2: private TemplateField __BuildControl__control5()
3: {
4: TemplateField field = new TemplateField();
5: field.HeaderTemplate = new CompiledTemplateBuilder(new BuildTemplateMethod (this.__BuildControl__control6));
6: field.EditItemTemplate = new CompiledBindableTemplateBuilder(new BuildTemplateMethod(this.__BuildControl__control7), new ExtractTemplateValuesMethod(this.__ExtractValues__control7));
7: return field;
8: }