从今天开始会有几篇日志,介绍 ASP.NET 4 Web Forms 中的一些重要变化,即生成干净的、标准兼容的、CSS友好的标记。今天介绍对服务器控件向客户呈现"ID"属性的更好控制。

html标签。干净的、基于标准的、CSS友好的标记

使用 ASP.NET Web Forms 的开发人员经常报怨的一件事情就是当使用服务器控件时,他们不能轻易地拥有产生干净的、CSS友好的输出和标记的能力。这些抱怨包括:

  • 自动生成的 ID 属性使得编写 JavaScript 和 用CSS做样式很困难
  • 控件使用表格而不是语义标记(尤其是 asp:menu 控件)使样式化丑陋
  • 一些控件呈现内联的样式属性,即使控件上没有设置样式
  • 视图状态太大

ASP.NET 4 为构建兼容标准的页面提供了更好的支持。内置的 <asp:> 服务器控件现在可以产生更干净的标记并支持CSS式样,从而解决了上述所有问题。

升级现有 ASP.NET Web Forms 应用程序时的标记兼容性

一个常见的问题就是,人们在听到 ASP.NET 4 带来的更干净标记时会问“很好——但我现存的应用程序怎么办?这些变化/改进在我升级时会带来破坏吗?”

为了确保不会破坏现存 ASP.NET Web Forms 应用程序的标记和式样,我们启用了一个配置标志——controlRenderingCompatibilityVersion——在 web.config 内部这样就能让你决定你是否想使用新的默认于ASP.NET 4应用程序中更干净的标记方法,或者为了兼容性的原因呈现和旧版本相同的标记:

p_w_picpath

当 controlRenderingCompatibilityVersion 标志设置为 "3.5",你的应用程序和服务器控件将会默认呈现VS2008和.NET3.5产生的标记。当 controlRenderingCompatibilityVersion 标志设置为 "4.0",你的应用程序和服务器控件会严格地遵守XHTML1.1规范,拥有更干净的客户端ID,呈现符合语义正确性,并移除多余的内联样式。

这个标志对使用 ASP.NET 4 构建的所有新的 ASP.NET Web Forms 应用程序都默认为 4.0。任何旧版本应用程序在使用VS2010升级后都会被升级向导自动把 controlRenderingCompatibilityVersion 标志设置为 3.5,以保证向后兼容。随后你可以可选地改变它(在应用程序级别,或者对每个页面或目录级别),如果你使用 CSS 并利用了新的标记呈现的话。

更干净标记主题:客户端 ID

拥有干净的、可预料的HTML 元素的 ID 属性是开发人员一直对 Web Forms 问的问题(像"ctl00_ContentPlaceholder1_ListView1_ctrl0_Label1"的ID值非常不受欢迎)。拥有对呈现的ID值的控制使得编写客户端JavaScript脚本变得非常容易,也使得使用 CSS 样式化元素变得更加容易,在大页面中可以减少产生的标记的大小。

控件新的 ClientIDMode 属性

ASP.NET 4 在 Control 基类上支持新的 ClientIDMode 属性。ClientIDMode 属性指示控件在呈现时应当如何产生客户端ID值。ClientIDMode 属性支持4个可能的值:

  • AutoID——像.NET 3.5那样呈现输出(即为了兼容性自动产生像 ctl00 这样前缀的 ID)
  • Predictable(默认)——去除任何"ctl00"这样的字符串,如果列表/容器连接了子ID的话(例如:id="ParentControl_ChildControl)
  • Static——把ID命名控制权完全交给开发者,即设置什么显示什么(例如:id="JustMyId")
  • Inherit——通知控件继承的父级容器控件的行为模式

ClientIDMode 属性可以直接在控件上设置(或在容器控件内部设置,这样内部的子控件会自动继承此设置):

p_w_picpath

或者可以在页面或用户控件级别指定(使用 <%@ Page %> 或 <%@ Control %> 指令),这时页面/用户控件内部的控件都会继承这个设置(控件可以覆盖这个值):

p_w_picpath

或者可以在应用程序的 web.config 文件内部设置,整个应用程序内部的页面都会继承这个设置(也可以覆盖):

p_w_picpath

这样就拥有了定制/覆盖命名行为的弹性。

示例:使用 ClientIDMode 属性控制非列表控件的 ID

让我们看看如何使用新的 ClientIDMode 属性来控制页面内部呈现元素的ID。创建一个叫做"SimpleControlExample.aspx"的简单页面,它基于叫做"Site.master"的母版页,页面中有一个 <asp:label> 控件,其值为"Message",这个控件置于叫做 "MainContent" 的 <asp:content> 容器控件中:

p_w_picpath

在后置代码中添加一些简单的代码,比如像下面这样在运行时动态地填充标签的 Text 属性:

p_w_picpath

如果使用 ASP.NET 3.5 运行这个应用程序(或者使用配置为使用 3.5 呈现或ClientIDMode=AutoID的 ASP.NET 4 应用程序),那么产生并发送到客户端的标记会像下面这样:

p_w_picpath

这个ID是唯一的(这挺好),但"ctl00"前缀让它显得比较丑陋(这不好)。

使用 ASP.NET 4 且 ClientIDMode 设置为 "Predictable" 的标记呈现

p_w_picpath

使用 ASP.NET 4,服务器控件默认使用 ClientIDMode="Predictable" 呈现它们的 ID。这确保了 ID 值仍然是唯一的,不会在页面上冲突,同时它让 ID 不再冗长更可预料。这意味着 <asp:label> 控件在 ASP.NET 4 中默认会产生像这样的标记:

p_w_picpath

注意,"ctl00" 前缀不见了。因为"Message"控件位于"MainContent"容器控件内部,默认地它的ID被设置为"MainContent_Message"以避免和页面其他控件出现潜在冲突。

使用 ASP.NET 4 且 ClientIDMode 设置为 "Static" 的标记呈现

有时不想让ID值层层嵌套,而是想和设置的一样呈现出来。要想做到这一点,可以使用 ClientIDMode=static,这样呈现的ID将会和在服务器控件上设置的完全相同。这将会呈现出下面的内容:

p_w_picpath

示例:使用 ClientIDMode 属性控件数据绑定控件的 ID

数据绑定的列表/网格控件在过去使用 Web Forms 自动产生ID时是最难以使用和样式化的。让我们看看使用 ASP.NET 4 定制 ListView 控件 ID 的场景。

下面的代码片断是一个 ListView 控件的例子,它显示了一个数据绑定集合的内容:

p_w_picpath

接着在后置代码中编写像下面这样的代码,动态地将数据源绑定到 ListView 中:

p_w_picpath

在运行时它默认会产生一个

  • 列表。注意,因为
    • 元素不是服务器控件,所以没有 ID 被呈现:

       

      p_w_picpath

      添加客户端ID到每一项

      现存假设我们想把客户端ID添加到输出中,这样我们能够通过 JavaScript 编程访问每一个

    • 。我们想让这些 ID 是唯一的、可预料的和可识别的。

       

      第一步是在模板内的每一个

    • 元素上指定一个id:

       

      p_w_picpath

      ASP.NET 4 默认会呈现像下面这样干净的 ID(没有类似于 ctl001 这样的ID呈现):

      p_w_picpath

      使用 ClientIDRowSuffix 属性

      上面的模板为每一个

    • 元素都生成了唯一的 ID,但是如果我们打算使用 JavaScript 在客户端编程访问它们,我们可能想让ID包含数据源的代码,这样可以让引用它们更容易。好消息是我们能够轻易地利用ASP.NET 4 数据绑定控件的新的 ClientIDRowSuffix 属性做到这一点:

       

      p_w_picpath

       

      现在不是有像"1", "2", "3" 这样的后缀,而是在ID中嵌入了 Airport.Code 值:

      p_w_picpath

      ClientIDRowSuffix 属性也能够用于其他数据绑定控件,如 GridView。

      总结

      ASP.NET 4 使得服务器控件和 Web Forms 应用程序能够生成更加干净的 HTML 标记。今天介绍了如何轻易地控制服务器控件在客户端呈现的ID值。在接下来的日志中我将介绍 ASP.NET 4 其他的一些标记改进。