简单数据绑定

  数据绑定表达式是由<%...%>包裹的可执行代码,以#号为前缀。它可以通过DataBoundLiteralControl类的实例以编程方式加以管理。

  数据绑定表达式通常从数据源获取数据,但并不是说它一定要从数据源获取数据,只要返回绑定的数据,任何可执行代码都是可以接受的。它仅在控件的DataBinding事件被触发时才执行计算。

  示例:<asp:label runat="server" Text='<%# DataTime.Now %>' />

  如果要对表达式用引号,应选择单引号。

  我们在页面中定义的数据绑定表达式会在DataBind被调用后计算。我们可以调用页面对象的DataBind方法,也可以调用指定控件上的。如果调用页面对象上的,便以递归方式调用定义在该页面所有控件的DataBind方法,如果不调用DataBind,<%#...%>永远不会被计算。

  数据绑定表达式非常适合基于页面中的其他控件更新当前控件的属性,且完全以声明方式编写。

<asp:DropDownList ID="SelColors" runat="server" AutoPostBack="True">
<asp:ListItem>Orange</asp:ListItem>
<asp:ListItem>Green</asp:ListItem>
<asp:ListItem>Red</asp:ListItem>
<asp:ListItem>Blue</asp:ListItem>
</asp:DropDownList>
<asp:Label runat="server" ID="lblColor" Text='<%# "<b>You Selected:</b>" + SelColors.SelectedValue %>' />

  注意:<%#...%>中的表达式可以为方法、常量、属性的结合体,只要最后的结果匹配绑定属性的类型即可。表达式的计算需要回发,并调用DataBind方法。为此,我们将AutoPostBack设为true,同时还需要调用页面或标签的DataBind方法来触发刷新过程。

protected void Page_Load(object sender, EventArgs e)
{
DataBind();
}

  考虑下面的代码:

ForeColor='<%# "orange" %>'
ForeColor="orange"

  以上代码只有第二条语句能被正常解析。原因是,数据绑定表达式需要确保其返回值的类型与控件属性的类型相匹配。但使用纯文本常量字符串没有问题,因为页面解析器会识别该表达式。如果需要解析器会插入适当的类型转换代码。

数据绑定表达式的内部实现

  如果Web页面中出现数据绑定表达式会发生什么情况呢?考虑下面的代码:

  <asp:label runat="server" id="today" text='<%# DateTime.Now %>' />

  在页面解析器处理.aspx源代码时,会为每个服务器控件生成一个工厂方法,该工厂方法所做的工作只是将标签的名称映射到一个服务器控件的类,并以赋值方式将标签中的属性(attribute)转换为对象的属性(property)。此外,如果有数据绑定表达式,解析器还会添加当前控件的DataBinding事件的处理程序。以下代码为该过程的执行结果:

private Control __BuildControlToday()
{
Label __ctrl = new Label();
this.today = __ctrl;
__ctrl.ID = "today";

__ctrl.DataBinding += new EventHandler(this.__DataBindToday);
return __ctrl;
}

  该处理程序将数据绑定表达式的内容分步赋给相应属性:

public void __DataBindToday(object sender, EventArgs e)
{
Label target;
target = (Label)sender;
target.Text = Convert.ToString(DataTime.Now);
}

  如果数据绑定表达式的值与期望的类型不匹配,则会出现编译错误。如果期望的类型为字符串,解析器便会通过Convert.ToString方法执行标准的转换。

DataBinder类

  Eval方法是一种运算符,专用于数据绑定表达式,用于访问绑定数据项的公共属性。ASP.NET 2.0之前的页面类中没有Eval方法,如果在ASP.NET 1.x应用程序中直接使用,则会产生编译错误。对于所有版本的ASP.NET来说,我们可以使用一个功能相同的方法,其名称也为Eval,但来自另一个类--DataBinder。

  通过Eval方法,我们能够访问绑定数据项的公共属性。但需要澄清,这个上下文中的公共属性是指什么?实现IEnumerable的类都可以绑定到控件上。具体的类包括DataTable(每个数据项在逻辑上对应一条记录),也包括自定义集合(每个数据项对应于给定类的实例)。Eval方法会针对数据项的属性集来查询数据项对象。代表记录的对象会返回所有字段的描述,而其他对象会返回各自的公共属性集。

  DataBinder类支持数据绑定表达式的生成和解析,其中的静态方法Eval十分重要。对于运行时的对象,该方法会使用反射来解析并计算表达式。该方法的一般语法为:

  <%# DataBinder.Eval(Container.DataItem, expression) %>

  Container.DataItem表达式用于引用一个对象,该对象中的表达式会被计算。expression一般为数据项对象中要访问字段的名称。它可以为包括索引或属性名的表达式。DataItem属性代表当前容器上下文中的对象。通常,容器一般为项目对象的当前实例。

更简洁的Eval

  原始的DataBinder.Eval语法在ASP.NET 2.0和更高版本中被简化了,代码可以这样写:

<%# Eval(expression) %>

  而ASP.NET 1.x只能接受下述表达式:

<%# DataBinder.Eval(Container.DataItem, expression) %>

  显然,ASP.NET 2.0及更高版本也完全支持DataBinder类。

  <%# ... %>分割符中出现的所有代码都会被ASP.NET运行特殊处理。当页面被编译后,对Eval方法的调用会被插入到页面的源代码中,并单独存在。下面的代码揭示了其内部细节:

object o = Eval("lastname");
string result = Convert.ToString(o);

  调用的结果会被转换为字符串,并赋给数据绑定控件,随后,数据绑定文本会被插入到页面控件树中。

  有了Eval方法,TemplateControl类得到了扩展,下面的伪码揭示了该方法的内部原理:

protected object Eval(string expression)
{
if(Page == null)
throw new InvalidOperationException(...);
return DataBinder.Eval(Page.GetDataItem(), expression);
}

  由此可见,Eval方法只是一个封闭器而已,它围绕着DataBinder.Eval方法构建而成。DataBinder.Eval方法由当前容器的数据项调用。当前容器的数据在数据绑定操作执行之前是空的,这是Eval与DataBinder.Eval间的主要差异。

  TemplateControl的Eval是一种数据绑定方法,仅用于数据绑定控件上下文中数据绑定操作期间。而DataBinder.Eval是一个完全自由的方法,可在任意位置使用。

默认数据项的获取

  在前面演示页面Eval方法的代码中用到了Page类的GetDataItem方法。这是什么呢?如前所述,简化的语法用到了一个默认的Container.DataItem上下文对象。GetDataItem正是返回该对象的函数。

  确切地讲,GetDataItem是基于栈的调用机制的终点(这种机制会跟踪页面当前的绑定上下文)。控件树中的每个控件会在各自的DataBind方法被调用时压入这个栈。DataBind方法返回时,相应控件会从栈中弹出。如果该栈为空,且试图以编程方式调用Eval,GetDataItem会抛出无效操作异常。总而言这,Eval的快捷方式只能在模板中使用,如果需要在其他位置访问数据项属性,必须借助于DataBinder.Eval,并显式地指示数据项对象。

Bind方法

  使用Eval方法的地方也可以使用Bind方法,二者的语法类似:

<asp:TextBox Runat="server" ID="TheNotes" Text='<%# Bind("notes") %>' />

  最大的不同在于Bind可以双向执行--读和写。例如,在设置Text属性时,Bind方法的行为与Eval一致。当Text被读取时,Bind会将值存储到集合中。ASP.NET中的数据绑定控件能自动获取这些值,并将它们填充插入或编辑命令的参数列表,并对数据源执行这些命令。传到Bind参数的名称必须与命令中参数的名称匹配。如,上述文本框会为@notes参数提供值。

用户定义的动态表达式

  数据绑定表达式不是真正的动态表达式,它们仅会在数据绑定调用上下文中被计算。

  动态表达式与数据绑定的语法相似,它使用的是$前缀。动态表达式会在页面编译时计算,表达式的内容会被提取,转换为代码,并注入为页面生成的代码中。有几个现有的表达式生成器:

  或要以声明方式将某个控件属性绑定到表达式的值,可使用以下模式:

  <%$ expression %>

  确切的语法取决于每种表达式关联的生成器的定义。但注意,页面主体中不允许出现文本表达式。换言之,我们只能对控件的属性应用表达式,而不能像下面这样使用:

<h1><%$ AppSettings:AppVersionNumber %></h1>

  我们应该将表达式封装在服务器控件中,最简单的是使用Literal控件,代码如下:

<h1><asp:Literal runat="server" Text="<%$ Resource:Resource, AppWelcome %>" /></h1>
<hr/>
<h1><asp:Literal runat="server" Text="<%$ AppSettings:AppVersionNumber %>" /></h1>
<hr/>

  显然,App_GlobalResource中要包含AppWelcome字符串资源,Web.Config文件中也要有AppVersionNumber设置。

  ConnectionStrings表达式对于数据源控件非常有用,它避免了在aspx文件中对连接字符串硬编码。

  开发者通过编写从ExpressionBuilder派生的类,可以定义其他的表达式。为使其能够识别并被正确处理,需要在web.config文件中注册自定义的表达式生成器。

转载于:https://www.cnblogs.com/free722/archive/2011/04/18/2019985.html

ASP.NET 3.5核心编程学习笔记(18):数据绑定表达式相关推荐

  1. ASP.NET 3.5核心编程学习笔记(55):自定义扩展程序控件的创建

    ASP.NET并没有包含对扩展程序的具体实现.然而,它定义了供所有自定义扩展程序和ACT中所有扩展程序使用的基类ExtenderControl.我们可通过该类创建自己的扩展程序.但并不建议这样做,因为 ...

  2. ASP.NET 3.5核心编程学习笔记(17):基于数据源的数据绑定

    从总体上讲,ASP.NET数据绑定模型可以分为三部分:数据绑定表达.传统数据源.数据源控件. 可用的数据源 在ASP.NET中,任何一个暴露IEnumerable接口的对象,都是有效的可绑定数据源.I ...

  3. 【C++】黑马程序员-C++核心编程学习笔记

    前言 根据黑马程序员C++课程内容,结合讲义,将自己学习C++的过程中将自己觉得有必要记下的笔记进行整理,方便复习回顾,编程环境为VSCode. 本阶段主要针对C++面向对象编程技术做详细讲解,探讨C ...

  4. 转 windows核心编程 学习笔记 目录

    windows核心编程--SEH(结构异常处理) SEH 的工作原理.         Windows 程序设计中最重要的理念就是消息传递,事件驱动.当GUI应用程序触发一个消息时,系统将把该消息放入 ...

  5. Python核心编程学习笔记(一)

    1.把一个字符串赋值给变量str.先用print来显示变量的内容,然后用变量名称来显示: >>>str = 'Hello World!' >>>print str ...

  6. windows核心编程学习笔记(六)动态链接库

    动态链接库有很多优点: •扩展了应用程序的特性 •可以用许多种编程语言来编写 •简化了软件项目的管理 •有助于节省内存 •有助于资源的共享 •有助于应用程序的本地化 •有助于解决平台差异 •可以用于一 ...

  7. python起步输入-[转载]python核心编程学习笔记-python起步

    python通过两种方式来实现你的需求:语句和表达式 语句:使用关键字组成命令 >>> print 'Hello wolrd!' Hello wolrd! 表达式:可以是算术表达式或 ...

  8. windows核心编程学习笔记(八)结构化异常处理(Structured Exception Handling)

    首先要要知道,结构化异常处理(SEH)和C++提供的异常处理不相同. 一.Termination HandlersTermination Handlers使用很简单.在想使用SEH处理的地方使用 __ ...

  9. Windows核心编程学习笔记

    字符串处理 strcpy和wcscpy不安全,是因为无法判断缓冲区最大长度的参数,不知道是否会破坏内存 一个进程-> 一个内核对象+一个地址空间 每个对象只是一个内存块 文件地址包括字节偏移量. ...

最新文章

  1. [高中作文赏析]感受冬天
  2. 年度盘点!必看AI顶会论文、Github高星项目大合集(附链接)
  3. 如何在ASP.NET页面中使用异步任务(PageAsyncTask)
  4. sql语句转linq的一个小工具
  5. 机器学习系列之手把手教你实现一个 naiveBayes
  6. C++ STL容器——序列式容器(array、vector、deque、list)
  7. 通过SQL直接插入、修改ArcGIS SDE空间表中的数据
  8. Axure+SVN——实现多人团队开发
  9. 混乱的Comcast
  10. Linux下的进程池(3)
  11. Python 调度算法 死锁 静动态链接 分页分段(七)
  12. Java序列化技术性能分析(JDK原生与Protostuff)
  13. 什么是Python解释器?
  14. java过滤器Filter实现敏感词汇过滤
  15. 苏州大学计算机复试python_苏州大学计算机考研复试经验总结
  16. 泊松分布–计算概率分布的公式
  17. 调制深度(modulation depth)是什么?
  18. 【Java异常】Caused by: com.sun.mail.iap.BadCommandException: A3 BAD invalid command or parameters的解决方案
  19. 树莓派3b+安装openwrt 配置wan lan和wifi
  20. osgEarth测高程方法

热门文章

  1. 4个最难的 Elastic Search 面试题
  2. 咖啡馆的故事:FTP, RMI , XML-RPC, SOAP, REST一网打尽
  3. IntelliJ IDEA 详细图解最常用的配置 ,适合刚刚用的新人。
  4. 微信为什么不丢消息?
  5. JVM:堆与栈的比较
  6. 沈阳大学计算机系教师,张春芳(信息工程学院)老师 - 沈阳大学 - 院校大全
  7. ps cs6 磨皮插件_磨皮就是几秒的事!2020顶级PS一件磨皮插件DR5、Portaiture分享
  8. 数据中心可以不设置柴发吗?
  9. 弱电工程数据中心计算机房内布线
  10. 读懂 | 路由器简史