科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道如何让Visual Studio和web标准联姻

如何让Visual Studio和web标准联姻

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

这篇文章可能会引起“网页设计者”的不安,因为可能会让他们产生“我必须要学习枯燥的代码”的误解; 这篇文章也可能会引起“程序员”的不安,因为可能会让他们产生“我必须学习繁琐的网页设计”的误解; 这篇文章也可能会引起“网页初学者”的不安,因为可能会让他们产生“我必须同时学习枯燥的代码和繁琐的网页设计”的误解。

作者:中国IT实验室 来源:中国IT实验室 2007年8月30日

关键字: Web标准 Visual Studio

  • 评论
  • 分享微博
  • 分享邮件

前言:
这篇文章可能会引起“网页设计者”的不安,因为可能会让他们产生“我必须要学习枯燥的代码”的误解;
这篇文章也可能会引起“程序员”的不安,因为可能会让他们产生“我必须学习繁琐的网页设计”的误解;
这篇文章也可能会引起“网页初学者”的不安,因为可能会让他们产生“我必须同时学习枯燥的代码和繁琐的网页设计”的误解。
其实大家都不需要感到不安,因为这篇文章的确是有点另类,它介于“网页设计”和“程序设计”之间,它就像前台和后台的一个桥梁。所以如果你对其中的一部分感到陌生甚至“完全看不懂”,没有关系,因为那一部分不是你所熟悉的领域。
记住:你有你熟悉的领域,你有你权威的领域,你有你作主的地盘! 没有必要刻意的去学习你不熟悉,甚至工作中用不到的知识领域。

正文:
“为什么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://www.cnblogs.com/Files/JustinYoung/adapter.rar

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

查看本文来源
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章