【原文地址】 Cleaner HTML Markup with ASP.NET 4 Web Forms – Client IDs (VS 2010 and .NET 4.0 Series) 【原文发表日期】 Tuesday, March 30, 2010 7:02 PM
【译注;由于工作繁忙,三月份之后一直没有时间翻译Scott Guthrie的博客。欣慰的是,新的贴子已由微软指定的专门公司做了翻译,这里我将补上其间没有翻译的一些技术贴子。 –思归】
这是我针对即将发布的VS 2010 和 .NET 4所撰写的 贴子系列的第十六篇。
今天的贴子是我将撰写的几个相关贴子的第一篇,主要讨论我们所做的一些重大改动,旨在使ASP.NET 4 的Web Forms生成整洁,与标准相兼容,CSS友好的标识。今天,我将讨论我们正在做的工作,以对由服务器控件显示到客户端的“ID”属性提供更好的控制。
【除了写博客外,我现在还使用Twitter发短贴和共享链接。请通过twitter.com/scottgu跟随我。】
整洁,与标准相兼容,CSS友好的标识
开发人员对ASP.NET Web Forms经常埋怨的一个东西,就是在使用服务器控件时,他们无法生成整洁的,CSS友好的输出和标识。下面是一些对早期ASP.NET版本的埋怨例子:
- 对HTML中自动生成的ID属性难以编写JavaScript来操作和使用CSS来做样式化
- 某些控件(特别是asp:menu控件)使用了表格(table),而不是更具语义的标识,使得样式很丑陋
- 一些控件生成了行内的样式属性,尽管控件上没设置样式属性
- ViewState经常是大得出奇
ASP.NET 4对建造与标准兼容的网页提供了更好的支持, ASP.NET 4 中内置的 <asp:> 服务器控件现在生成干净了许多的标识, 支持CSS样式化,来帮助解决上面提到的所有问题。
升级现有的ASP.NET Web Forms应用时的标识兼容问题
当听说ASP.NET 4即将提供整洁的标识时,大家常问的一个问题是,“太棒了,但我现有的应用怎么办?在我升级后,这些变动或改进会不会造成问题?”
为帮助确保我们不会破坏现有的ASP.NET Web Forms应用中对标识和样式所做的假设,我们在 web.config中启用了一个配置标记,controlRenderingCompatbilityVersion,让你决定你是想使用新的ASP.NET 4应用默认的新的整洁标识方式呢,还是为兼容起见,显示与所使用的早期ASP.NET版本同样的标识:
当controlRenderingCompatbilityVersion属性设置为“3.5”时,你的应用和服务器控件会默认使用与VS 2008 和 .NET 3.5一样的标识生成机制来生成输出。当 controlRenderingCompatbilityVersion属性设置为“4.0” 时,你的应用和服务器控件会严格遵循XHTML 1.1规格,生成整洁的客户端ID,显示时以语义正确为宗旨,除去不相关的行内样式。
在使用ASP.NET 4建造的所有新的 ASP.NET Web Forms中,该属性的默认值是4.0。使用VS 2010升级的任何以前的应用,都会被升级向导设置controlRenderingCompatbilityVersion为3.5,以确保向后的兼容性。然后你可以选择改变这个设置(在应用级别,或在web.config文件中局限于页面或目录级别),如果你决定改动页面来使用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一样的输出(为兼容起见,自动生成的ID还会含有象ctrl00这样的前缀)
- Predictable (默认值)–除去任何“ctl00” ID 字符串,如果是列表或容器控件,则把子控件的ID串列起来 (例子:id=”ParentControl_ChildControl”)
- Static (静态)–将ID命名控制完全交给开发人员,他们设置什么ID值,就显示什么值 (例子: id=”JustMyId”)
- Inherit (继承)–告诉控件使用父容器控件的命名行为模式
ClientIDMode属性可以直接设置在单独的控件上(或在容器控件中, 内中包含的控件会默认继承该设置):
或在页面或用户控件层次设置(使用 <%@ Page %> 或 <%@ Control %> 指令),这样在页面或用户控件中的控件会继承这个设置(还可以选择覆盖这个设置):
也可以在应用的web.config文件中设置,这样应用中的所有页面都会继承这个设置(还可以选择覆盖这个设置):
这给予了你任意定制/覆盖命名行为的灵活性。
例子:使用ClientIDMode属性控制非列表控件的ID
让我们来看一下,如何使用新的ClientIDMode属性来控制网页中 “ID” 元素的生成。为帮助示范,我们创建了一个简单的网页,名为“SingleControlExample.aspx”,是基于名为“Site.Master”的母版页的,内含单个<asp:label> 控件,其ID为“Message” ,该控件是包含在名为 “MainContent”的 <asp:content>容器控件中的:
然后在后台代码中,我们加了一些象下面这样的简单的代码,在运行时动态填充Label的 Text属性:
如果我们是在 ASP.NET 3.5 中 运行该应用(或将ASP.NET 4应用配置使用了3.5显示方式或ClientIDMode=AutoID运行的话),那么生成发送到客户端的标识会是这样的:
这个ID是独特的(是好事),但因为其“ct100”前缀,又很丑陋(是坏事)。
使用ASP.NET 4以及ClientIDMode被设置为 “Predictable”时的标识显示
在ASP.NET 4中,服务器控件现在默认使用 ClientIDMode=”Predictable”来生成它们的ID。这帮助确保ID值依然是独特的,在页面上没有冲突,但同时也使得ID不那么冗长,比较可以预料。这意味着我们上面的 <asp:label> 控件生成的标识在ASP.NET 4默认的情形下,会是这样的:
注意“ct100”前缀现在没有了。因为 “Message” 控件是内嵌在“MainContent” 容器控件中的,在默认情形下,它的ID会被前缀,成为 “MainContent_Message”,以避免与网页上的其他控件相冲突。
使用ASP.NET 4以及ClientIDMode被设置为“Static””时的标识显示
但有时,你不想要你的ID值被分层嵌套,而只是想显示你设置的任何值。要启用这个的话,你现在可以使用ClientIDMode=Static,这样显示的ID值会跟你在服务器端在你的控件上设置的ID值完全一样。这在ASP.NET 4中会导致下述标识:
这个选项现在给予你完全控制控件发送到客户端的ID的能力。
例子:使用ClientIDMode属性控制数据绑定列表控件的ID
数据绑定的列表/网格在Web Form自动生成的ID方面一直以来一直是最难使用和样式化的。现在让我们来看一个场景,看如何在ASP.NET 4中对使用ListView控件生成的ID进行定制。
下面的代码片段是个ListView控件的例子,显示了一个数据绑定集合(机场)中的内容:
然后,我们在后台代码中编写下述代码来动态绑定一个机场列表到上面的ListView上:
然后在运行时,这会默认生成象下面这样的 <ul> 机场列表。注意,因为 ListView模板中的 <ul> 和 <li> 元素不是服务器控件,在标识中是不会有ID的:
给每个行项添加客户端ID
现在,说我们想要给输出添加客户端ID,这样我们可以通过JavaScript使用编程手法来访问每个<li>。我们想要使得这些ID是独特的,可预料的,以及可辨识的。
第一种做法是将模板中的每个 <li> 元素标记为服务器控件(给它一个runat=server属性),并且给其一个id为“airport”:
在默认情形下,ASP.NET 4现在会生成象下面这样整洁的ID(不生成象ctl001这样的ID):
使用ClientIDRowSuffix属性
我们上面的模板给每个 <li> 元素生成了独特的ID,但假如我们想要在客户端使用JavaScript通过编程手法来访问它们的话,我们也许想要使得ID包含对应的机场的Code属性,以简化引用。好消息是,我们可以轻松地达到目的,通过利用ASP.NET 4中数据绑定控件上的ClientIDRowSuffix属性来更好地控制单独行元素的ID。
要实现的话,我们将在ListView控件上设置ClientIDRowSuffix属性为“Code”。这告诉ListView在生成ID时,使用Airport类的“Code”数据绑定属性:
这样,行的ID后缀不再是“1”, “2”, 或 “3”,而是将Airport.Code值嵌合到ID中去了(例如:_CLE, _CAK, _PDX等等):
你也可以在其他数据绑定控件(象GridView)上使用 ClientIDRowSuffix。在你想要在客户端对行元素进行编程,在JavaScript代码中使用干净的/可辨识的ID来轻松地引用这些元素时,这会非常有用。
结语
ASP.NET 4允许服务器控件和你的Web Forms应用生成干净许多的HTML标识。
在今天的贴子中,我讨论了如何轻松地控