如何让Visual Studio和web标准联姻(附源码下载)
前言:
这篇文章可能会引起“网页设计者”的不安,因为可能会让他们产生“我必须要学习枯燥的代码”的误解;
这篇文章也可能会引起“程序员”的不安,因为可能会让他们产生“我必须学习繁琐的网页设计”的误解;
这篇文章也可能会引起“网页初学者”的不安,因为可能会让他们产生“我必须同时学习枯燥的代码和繁琐的网页设计”的误解。
其实大家都不需要感到不安,因为这篇文章的确是有点另类,它介于“网页设计”和“程序设计”之间,它就像前台和后台的一个桥梁。所以如果你对其中的一部分感到陌生甚至“完全看不懂”,没有关系,因为那一部分不是你所熟悉的领域。
记住:你有你熟悉的领域,你有你权威的领域,你有你作主的地盘! 没有必要刻意的去学习你不熟悉,甚至工作中用不到的知识领域。
正文:
“为什么Microsoft Visual Studio .NET 的label控件打到前台变成了span?”,“Microsoft Visual Studio .NET 的服务器段控件的设计根本就不符合web标准设计”, “微软对web标准支持太差了!”……
现在做大型B/S模式的商业项目开发似乎很难不考虑使用Microsoft Visual Studio .NET 2005(或以上版本),比较有深远考虑的B/S模式的项目又似乎很难不考虑用Web标准进行设计。而当一个B/S模式的商业项目既很大型,又需要有深远考虑的时候,Microsoft Visual Studio .NET 2005 和 “Web标准设计”相交了。当时我们遗憾的看到它们并没有“一见钟情”或者“相见恨晚”。而是“冲突不断”。难道它们就不能更好的相处吗?非也,非也,两口子闹别扭是正常的,只要任意一方能够有包容的心,婚姻还是可以很幸福的。“人妖”尚有一颗包容的心(参看《大话西游》),况VS2005乎?其实VS2005也有着一颗很“包容”的心,让它能和web标准更好的相处。
理论基础
首先感谢一下“adapter设计模式”,然后感谢一下VS2005的强大。正是它们让VS2005能够和web标准可以融洽的相处。
我们都知道VS中服务器端控件label打到前台以后就编程了span,但是为什么会这样,是什么让
变成
其实完成这个任务的神秘机器就是“适配器(adapter)”——
正是adapter让服务器端控件,变成了客户端的html标签。但是它到底又是怎么工作的呢?因为这个牵扯到“控件编程”的概念,而此概念似乎很难用两三句话简单的说明,所以这里不再详述。感兴趣的朋友可以在MSDN中关注下面的内容“HtmlContainerControl.Render”、“ HtmlTextWriter”、“ System.Web.UI.HtmlControls”……
虽然这里不会详细的讲解“控件编程”的知识,不过,大家可以放心,我们仍然会用一个实例来讲解怎么用adapter来实现将服务器端控件Label打到前台为Label标签而不是原来的span标签。
在讲实例之前我们要先讲一下VS2005中的browsers元素。这是一个很了不起的东西。它的设计本意可不是将服务器端控件换个标签呈现出来那么简单。先引用MSDN上的原文——
“浏览器定义文件包含各个浏览器的定义。在运行时,ASP.NET 使用请求标头中的信息来确定发出请求的浏览器的类型。随后,ASP.NET 使用 .browser 文件来确定浏览器的功能,以及如何向该浏览器呈现标记。对于希望创建可以在移动设备上查看的应用程序的 Web 开发人员,这很有用。因为这样可以利用控件适配器根据设备类型改编 ASP.NET Web 服务器控件的行为。”
MSDN是有个坏毛病,就是将答案回答的看不懂。上面这些话到底是什么意思呢?其实很简单——利用browsers元素,就可以判断浏览网页的设备(是浏览器呀?还是PDA呀?还是手机呀?如果是浏览器,那么是什么浏览器呀?IE还是FF,还是其他浏览器?如果是IE,那是那个版本呢?是IE6还是IE7?如果是手机,那么是什么牌子的手机呀?爱立信的还是摩托的?这些都能够识别出来),然后根据不同的浏览设备向浏览设备进行不同的标记呈现!
这个东西包含了两个部分:1:可以判断不同的浏览设备;2:可能向不同的浏览设备呈现不同的东西,例如可以将<asp:Label ID="Label1" runat="server"></asp:Label>在IE6中呈现为span,而在爱立信手机中程序为label。browsers的确是个很了不起的东西,因为它轻松地解决了“网页设计师”一直以来面对的一个头疼的问题——根据不同的浏览器对页面进行不同的渲染。(虽然以前用一些css hack技巧也能达到目的,但是跟这个比起来,那个的确是落后、狭隘、不值得推荐的办法)
代码实例
“光说不练假把式”,下面我们就根据实例来体会一下browsers和adapter的强大。
实例一:很简单,就是将备受非议的“服务器端控件Label打到前台为什么是span?”变成达到前台是label。
Setp1:vs2005中建一个web工程。在一个新的页面上拖个Label服务器控件。在工程中新添加一个browsers文件取名为test.browser,参看下图(十分抱歉,是日文的VS2005,虽然已经跳槽,但是现在仍然在原公司做交接工作):
Setp2:删除test.browser自动生产的代码,添加我们的代码如下:
<browser refID="default">
<controlAdapters>
<adapter controlType="System.Web.UI.WebControls.Label" adapterType="LabelAdapter" />
</controlAdapters>
</browser>
</browsers>
这段代码的意思是为所有的Label服务器端控件指定名为“LabelAdapter”的适配器类型。
Setp3:创建一个名为“LabelAdapter”的类。类代码如下(解释见注释):
Imports System.Web.UI
Imports System.Web.UI.WebControls
Public Class LabelAdapter
Inherits System.Web.UI.WebControls.Adapters.WebControlAdapter
Protected Overloads ReadOnly Property Control() As Label
Get
Return DirectCast(MyBase.Control, Label)
End Get
End Property
Protected Overrides Sub RenderBeginTag(ByVal writer As HtmlTextWriter)
writer.WriteLine() '换行
writer.AddAttribute(HtmlTextWriterAttribute.Id, Control.ClientID) '添加一个id属性
If Not String.IsNullOrEmpty(Control.ControlStyle.CssClass) Then '如果设置了cssClass就添加一个Class属性
writer.AddAttribute(HtmlTextWriterAttribute.Class, Control.ControlStyle.CssClass)
End If
writer.RenderBeginTag(HtmlTextWriterTag.Label) '标签头是label
writer.Indent = writer.Indent + 1 '增加缩进
End Sub
Protected Overrides Sub RenderEndTag(ByVal writer As HtmlTextWriter)
writer.Indent = writer.Indent - 1 '减少缩进
writer.RenderEndTag() '闭合标签
writer.WriteLine()
End Sub
Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
RenderContent(writer)
End Sub
Private Sub RenderContent(ByVal writer As HtmlTextWriter)
writer.Write(Control.Text) '打出控件的text属性内容
End Sub
End Class
Step3:编译、运行。
查看页面的源文件。我们发现,服务器端的Label控件打到前台的已经不是span,而是label了。这样我们就将服务器端控件的呈现进行了重新的设置。
实例二:根据浏览器的类型,设置不同的样式。如果是IE浏览器就对刚才的那个label使用“cssTest”样式class,如果是Firefox浏览器就对刚才的那个label设置“cssTest_FF”样式class。
Step1:在页面上写2个样式class,参考如下:
.cssTest{
color:red;
}
.cssTest_FF{
color:green;
}
</style>
Setp2:将test.browser里面的代码删除,添加新的代码如下:
<browser refID="IE">
<controlAdapters>
<adapter controlType="System.Web.UI.WebControls.Label" adapterType="LabelAdapter" />
</controlAdapters>
</browser>
<browser refID="MozillaFirefox">
<controlAdapters>
<adapter controlType="System.Web.UI.WebControls.Label" adapterType="LabelAdapter_FF" />
</controlAdapters>
</browser>
</browsers>
Setp3:创建一个名为“LabelAdapter_FF”的类。类代码如下(解释见注释):
Imports System.Web.UI
Imports System.Web.UI.WebControls
Public Class LabelAdapter_FF
Inherits System.Web.UI.WebControls.Adapters.WebControlAdapter
Protected Overloads ReadOnly Property Control() As Label
Get
Return DirectCast(MyBase.Control, Label)
End Get
End Property
Protected Overrides Sub RenderBeginTag(ByVal writer As HtmlTextWriter)
writer.WriteLine()
writer.AddAttribute(HtmlTextWriterAttribute.Id, Control.ClientID)
If Not String.IsNullOrEmpty(Control.ControlStyle.CssClass) Then
writer.AddAttribute(HtmlTextWriterAttribute.Class, Control.ControlStyle.CssClass & "_FF") ‘用原来cssClass加上”_FF”这个样式class
End If
writer.AddStyleAttribute("font-weight", "bold") ’也可以直接样式属性
writer.RenderBeginTag(HtmlTextWriterTag.Div) ‘这里换成div了,只是演示而已
writer.Indent = writer.Indent + 1
End Sub
Protected Overrides Sub RenderEndTag(ByVal writer As HtmlTextWriter)
writer.Indent = writer.Indent - 1
writer.RenderEndTag()
writer.WriteLine()
End Sub
Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
RenderContent(writer)
End Sub
Private Sub RenderContent(ByVal writer As HtmlTextWriter)
writer.Write(Control.Text)
End Sub
End Class
Step4:编译、运行。
在IE和FF中分别查看源文件,发现不仅应用的样式不同,连打到前台的标签都不同了。效果图如下:
后记:很多朋友应该知道“ASP.NET CssFriendlyAdapters”这个工具,其实原理就是这个。不过那个能够解决更大型的控件的呈现而已。有兴趣的朋友可以自己搞搞。
vs2005中browsers是个很了不起的东西。小弟才浅,这里只是利用了它很少的一部分功能,但是依然解决了一直困扰“网页设计师”的两个问题。
虽然从社会分工的角度上来看,前台网页制作和后台编码是应该分开进行的。但是在项目设计阶段,如果有一个既懂前台网页设计又懂后台程序的角色好像也挺不错的。
源代码下载:https://files.cnblogs.com/JustinYoung/adapter.rar
感谢于何的技术指导。没有他,便没有此篇文章。谨此奉上真挚的感谢。
我现在仍然在原来的那家日企公司做一些交接上的工作。主要就是做了关于web标准设计的3期“知识广播”,明天将是最后一讲。也很可能将是我对原公司最后贡献。
请允许我在这里表达一下对原公司两个人的特别感谢:项目经理“朱王伟”,从他身上学习了很多管理方面的知识。技术支持“于何”,技术好的没话说,几乎所有的项目架构和设计都由他带头,我之所以能接触到很多新的知识领域,很多都是因为他的指导。 真诚的说句——“谢谢!”
keyword:vs2005支持web标准,微软支持web标准,微软支持,控件编程,vs2005 adapter,vs2005 browsers,CssFriendlyAdapters