在ASP.NET我们在使用Repeater,DetailsView,FormView,GridView等数据绑定模板时,都会使用或这样的语法来单向或双向绑定数据。但是我们却很少去了解,在这些语法的背后,ASP.NET究竟都做了哪些事情来方便我们使用这样的语法来绑定数据。究竟解析这样的语法是在编译时,还是运行时?如果没有深入去了解,我们肯定不得而知。这个简短的系列文章就是带我们大家一起去深入探究一下ASP.NET绑定语法的内部机理,以让我们更加全面的认识和运用它。

事件的起因是,我希望动态的为Repeater控件添加行项模板,我可以通过实现ITempate接口的方式来动态添加行模板。并希望它通过普通的页面绑定语法来完成数据字段的绑定功能,如下就是一个简单的例子:

 
 
 
   DynamicTemplate : ITemplate
 {
      DynamicTemplate()
     {
         
         
         
     }
      ITemplate Members
  
       InstantiateIn(Control container)
     {
         TextBox textBox =  TextBox();
         textBox.Text = ;
         container.Controls.Add(textBox);
     }
     
 }

在这个例子中,我在模板中添加了一个TextBox控件,并指定它的绑定字段是“ID”。但是这做法,能否实现我们实现我们需要的功能呢?答案是否定,每一行的TextBox的值都是"",而不会像我们希望的那样去绑定ID字段。从结果来分析原因,我们可以非常容易得出,这段绑定语法并没有得到ASP.NET运行时的承认,那么页面中使用相同的语法为什么可以呢?故事就是从这里开始的。

我们首先要去了解下,在页面中使用这样的语法ASP.NET都为我们做了哪些事情呢?要了解这个,我们要找到.aspx文件在首次运行时动态编译的程序集。

我们都知道,在ASP.NET运行时,也会把.aspx文件编译成一个动态类,这个类是继承于.aspx的Page指令中Inherits属性指定的类并且同时也直接实现了IHttpHandler接口。这个动态类会负责创建页面中使用的各种服务器端控件的实例,并且ASP.NET运行时会负责解析的编译.aspx中存在的服务器端代码(包括绑定语法)并将这些代码编译到这个页面类。WebSite工程和Web Application在页面文件上有些不同,WebSite工程的每个页面最多可以有两个文件:.aspx和.aspx.cs文件;而在Web Application还可以包括.aspx.designer.cs文件,这个文件所起的作用也非常有限,也就是为了能在页面代码中使用服务器端、控件实例而定义的一个实例变量,仅此而已。所以在设计时WebSite具备更多的动态行为,而在运行时WebSite工程和Web Application并没有太大区别。

如何得到页面的动态类呢?要首先得到这个页所在的动态程序集,在Vista以前的操作系统上,一般是在:%SystemRoot%\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files 文件夹下,而在Vista中,而会在:%USERPROFILE%\AppData\Local\Temp\Temporary ASP.NET Files下。那么如何快速得到程序集的路径和名称?你可以让你的Web工程动态编译出错(比如重复的类名),就可以快速定位到当前动态程序集的目录了。

动态类中会有很多的内容,我们不作更多的分析,我们把目光集中绑定代码上。假设现在页面上有这么一段Repeater绑定代码:

  ID=>
     
         
             
                 
                     ID
                 
                 
                     电流{a}
                 
                  电压(V)
                 
                     备注
                 
                 
                     名称]
                 
             
     
     
         
             
                 
             
             
                 
             
             
             
                 
             
             
                 名称]")%>
             
         
     
     
         
     
 

那么在动态类中,相应的会有这样的一段函数,是用来创建ID为repeater的控件实例:

 [DebuggerNonUserCode]
  Repeater __BuildControlrepeater()
 {
     Repeater repeater =  Repeater();
     .repeater = repeater;
     repeater.HeaderTemplate =  CompiledTemplateBuilder( BuildTemplateMethod(.__BuildControl__control4));
     repeater.ItemTemplate =  CompiledTemplateBuilder( BuildTemplateMethod(.__BuildControl__control5));
     repeater.FooterTemplate =  CompiledTemplateBuilder( BuildTemplateMethod(.__BuildControl__control7));
     repeater.ID = ;
      repeater;
 }
  
  

CompiledTempateBuilder和BuildTemplateMethod只是模板实例化的一个中介,真正用于添加模板内容的是后面的那些私有函数,如ItemTempate的模板内容实例的创建就在__BuildControl__control5函数中,这个函数原型定义是:

 [DebuggerNonUserCode]
   __BuildControl__control5(Control __ctrl)
 {
     DataBoundLiteralControl control = .__BuildControl__control6();
     IParserAccessor accessor = __ctrl;
     accessor.AddParsedSubObject(control);
 }
  

在这个函数里,调用了另一个私有函数this.__BuildControl__control6,这个函数返回的一个DataBoundLiteralControl对象,并将对象输出添加到__ctrl参数。事实上,只要我们去阅读CompiledTempateBuilder就发现在,这里的__ctrol对象就是我们在实例化模板时传入的对象,也就是ITemplate中的InstantiateIn方法的那个container参数对象。

为什么使用的是AddParsedSubObject方法,使用这个方法添加子控件相当于告诉父控件,这是一个已经解析好的子控件对象,不需再去将控件解析成HTML代码,而在输出时直接输出Text属性的值即可。从这里我们还可以得知DataBoundLiteralControl的对象,事实上就是承担了字符串拼接的职责,这一点我们可以在后面的分析中得以验证。

__BuildControl__control6私有函数的定义如下:

 [DebuggerNonUserCode]
  DataBoundLiteralControl __BuildControl__control6()
 {
     DataBoundLiteralControl control =  DataBoundLiteralControl(5, 4);
     control.TemplateControl = ;
     control.SetStaticString(0, 
     control.SetStaticString(1, 

\r\n \r\n ");

     control.SetStaticString(2, 

\r\n \r\n \r\n ");

     control.SetStaticString(3, 

\r\n \r\n ");

     control.SetStaticString(4, 

\r\n \r\n ");

     control.DataBinding +=  EventHandler(.__DataBind__control6);
      control;
 }

在这个函数里面,创建了一个DataBoundLiteralControl对象,并将页面上定义的模板的静态HTML代码添加到该的静态字符串数组里,并且设置了它的绑定事件代理函数__DataBind__control6,该函数的定义:

   __DataBind__control6( sender, EventArgs e)
 {
     DataBoundLiteralControl control = (DataBoundLiteralControl) sender;
     RepeaterItem bindingContainer = (RepeaterItem) control.BindingContainer;
     control.SetDataBoundString(0, Convert.ToString(.Eval(), CultureInfo.CurrentCulture));
     control.SetDataBoundString(1, Convert.ToString(.Eval(), CultureInfo.CurrentCulture));
     control.SetDataBoundString(2, Convert.ToString(.Eval(), CultureInfo.CurrentCulture));
     control.SetDataBoundString(3, Convert.ToString(.Eval(), CultureInfo.CurrentCulture));
 }

在这个函数中,我们看到了真正的数据绑定代码了,它调用了TemplateControl的Eval方法来将当前数据项的相应字段的值取出,并按一定的格式转化后添加到DataBoundLitreralControl对象中,并在DataBoundLiteralControl将StaticString和DataBoundString字符串数组按一定的顺序拼接起来,作为Text属性的输出值。而容器控件则直接向客户端输这段HTML。

下面,我们还有必要来分析下TemplateControl中的Eval方法,这个方法有两种重载,简单起见,我们来分析较为简单的重载:

    Eval( expression)
 {
     .CheckPageExists();
      DataBinder.Eval(.Page.GetDataItem(), expression);
 }

这个方法,使用了DataBinder.Eval静态方

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12639172/viewspace-402158/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12639172/viewspace-402158/

【阿不】深入ASP.NET数据绑定(上)相关推荐

  1. 深入ASP.NET数据绑定(上)

    转载自阿不 http://hjf1223.cnblogs.com/ 在ASP.NET我们在使用Repeater,DetailsView,FormView,GridView等数据绑定模板时,都会使用&l ...

  2. 深入ASP.NET数据绑定(中)——数据双向绑定机理

    转载自 阿不 http://hjf1223.cnblogs.com/ 在上一篇<深入ASP.NET数据绑定(上)>中,我们分析了在.NET中的数据绑定语法的一些内部机理.简单说来就是ASP ...

  3. 【阿不】深入ASP.NET数据绑定(下)—多样的绑定方式

    在这个系列的上篇中介绍了数据绑定语法的原理以及.NET中如何实现单向绑定,中篇我们简单的介绍了ASP.NET 2.0 中新增的Bind语法配合DataSourceControl来实现数据的自动双向绑定 ...

  4. 【阿不】深入ASP.NET数据绑定(中)—数据双向绑定机理

    在上一篇<深入ASP.NET数据绑定(上)>中,我们分析了在.NET中的数据绑定语法的一些内部机理.简单说来就是ASP.NET在运行时为我们完成了页面的动态编译,并解析页面的各种服务器端代 ...

  5. ASP.NET 获取上一个页面的Url链接

    ASP.NET 获取上一个页面的Url链接Uri Url = HttpContext.Current.Request.UrlReferrer;

  6. 关于ASP无组件上传在2003下出错

    关于ASP无组件上传在2003下出错.. 问题描述: asp无组件上传程序无法上传较大的文件"Request 对象 错误 ASP 0104 : 80004005",(大概大于100 ...

  7. ASP.NET文件上传

    例子一: 用一个正则表达式来验证上传文件的类型,去掉<asp:RegularExpressionValidator/> 能上传所有 Default.aspx: <%@ Page La ...

  8. ASP.NET文件上传和下载

    大学最近作出相关的需求进行上传和下载文件的网站(求为:站点发布的通知,在后台要能给每一个通知加入附件.在前台要能显示并下载附件),之前仅仅是学习过关于上传的 理论知识,这里实践了一下下,与大家分享一下 ...

  9. 6行代码实现ASP无组件上传

    目前有很多无组件上传类,我大概看了一下,大多写的相当复杂,有的居然还只能传文本,最关键的是没有10行代码以下的:),我花了一个晚上时间研究了一下ADODB.Stream,并且用了6行代码实现了无组件上 ...

  10. ASP.NET MVC3 上传头像图片并截图

    关于上传头像并且截图网上应该有很多资料,大多都是JQuery插件,用起来不是很方便 本文所介绍的方法将快速完成一个"上传头像图片并截图",只需要修改少量的代码 我们先来看看完成后的 ...

最新文章

  1. 怎样在两小时内搞定 OpenStack 部署?
  2. linux https重定向,Linux | Apache环境下强制http跳转至https的配置总结
  3. linux安全 4a标准_Linux的未来,提高安全性的开放标准等等
  4. python匹配字符串_字符串匹配算法之Kmp算法(Python实现)
  5. 计算机科学学院参加些什么比赛,【安全月进行时】计算机科学学院成功举办2019年实验室安全知识竞赛活动...
  6. PancakeBunny获160万美元战略融资,Binance Labs领投
  7. 莺颠燕狂的拼音及解释
  8. SpringSession
  9. 『Asp.Net 组件』Asp.Net 服务器组件 内嵌CSS:将CSS封装到程序集中
  10. 实验固体力学类毕业论文文献包含哪些?
  11. WPS2000系列之四图文混编(转)
  12. 计算机的声卡怎么安装教程,图文详解如何安装声卡驱动_给电脑安装声卡驱动的详细教程...
  13. 你根本就不会使用Notes!
  14. 新手python爬虫代码-Python爬虫实战之取电影天堂,,新手练手项目
  15. 互联网毒瘤——内容农场
  16. xcode14 Command Swift Driver Compilation Requirements emitted errors but did not ret
  17. Windows快捷键和基本DOS命令
  18. SAP EWM TCODE list
  19. 减少银行和金融机构的客户流失
  20. LeetCode1-620题汇总,希望对你有点帮助!

热门文章

  1. Vue Router 路由实现原理
  2. Android Studio配置SVN及使用
  3. otg和充电共用问题
  4. 小班语言游戏教案%3c我的五官%3e,小班语言教案《我的五官》三篇
  5. jQuery 循环遍历方法总结+综合案例
  6. jsqlparser
  7. 基于深度学习的物体图像识别
  8. SpringBoot中MBG的使用
  9. 【STM32】基于F103C8T6和ESP01远程控制灯光开关(SG90舵机控制)
  10. java 吃饭 洗手_舒肤佳“洗手吃饭”的第五年:营销如何化繁为简?