如何让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自动生产的代码,添加我们的代码如下:

< browsers >
  
< browser  refID ="default" >
    
< controlAdapters >
      
< adapter  controlType ="System.Web.UI.WebControls.Label"  adapterType ="LabelAdapter"   />
    
</ controlAdapters >
  
</ browser >
</ browsers >

这段代码的意思是为所有的Label服务器端控件指定名为“LabelAdapter”的适配器类型。
Setp3:创建一个名为“LabelAdapter”的类。类代码如下(解释见注释):

Imports  System
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,参考如下:

 <style type="text/css">
    .cssTest
{
    color
: red ;
    
}
    .cssTest_FF
{
    color
: green ;
    
}
 </style>

Setp2:将test.browser里面的代码删除,添加新的代码如下:

< browsers >   
  
< 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
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是个很了不起的东西。小弟才浅,这里只是利用了它很少的一部分功能,但是依然解决了一直困扰“网页设计师”的两个问题。
虽然从社会分工的角度上来看,前台网页制作和后台编码是应该分开进行的。但是在项目设计阶段,如果有一个既懂前台网页设计又懂后台程序的角色好像也挺不错的。

源代码下载:http://files.cnblogs.com/JustinYoung/adapter.rar

感谢于何的技术指导。没有他,便没有此篇文章。谨此奉上真挚的感谢。


我现在仍然在原来的那家日企公司做一些交接上的工作。主要就是做了关于web标准设计的3期“知识广播”,明天将是最后一讲。也很可能将是我对原公司最后贡献。
请允许我在这里表达一下对原公司两个人的特别感谢:项目经理“朱王伟”,从他身上学习了很多管理方面的知识。技术支持“于何”,技术好的没话说,几乎所有的项目架构和设计都由他带头,我之所以能接触到很多新的知识领域,很多都是因为他的指导。 真诚的说句——“谢谢!”


keyword:vs2005支持web标准,微软支持web标准,微软支持,控件编程,vs2005 adapter,vs2005 browsers,CssFriendlyAdapters
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值