公  告
 
  站点日历
 
  日志分类
 
  最新日志
 
  最新评论
 
  最新留言
 
  用户登陆
 
  日志搜索
 
  统计信息
 



  友情连接
 
  开发和使用自定义服务器控件之一
[ 2008-9-10 8:04:00 | By: gmfzh ]
 
 

开发和使用自定义服务器控件
此演练演示如何创建和编译自定义 ASP.NET 服务器控件以及如何在页中使用该控件。
通过此演练,您将学会如何执行以下任务:
1、创建一个 ASP.NET 服务器控件。
2、向该控件及其成员添加元数据以控制安全性和设计时行为。
3、使用 ASP.NET 网站中的 App_Code 目录对控件进行测试(无需手动编译步骤)。
4、在配置文件和该控件的程序集中指定一个标记前缀。
5、将该控件编译为一个程序集并将其添加到 Bin 目录中。
6、将一个位图嵌入到该控件的程序集中,以作为可视化设计器的工具箱图标使用。
7、在页中使用已编译的控件。

    可视化设计工具(如 Microsoft Visual Studio 2005)可以简化控件的开发过程,但并不是创建或生成自定义控件的必不可少的工具。可

以通过使用任何文本编辑器创建控件,并使用属于 .NET Framework SDK 一部分的编译器从命令行生成这些控件。无论以何种方式创建控件,

在可视化设计器中控件的设计时外观和行为都将相同。页开发人员可将控件添加到可视化设计器的工具箱,可将其拖动到设计图面上,还可以在属性浏览器中访问其属性和事件。在有些可视化设计器(如 Visual Studio 2005)中,自定义控件还可自行支持 IntelliSense。

    (一)创建服务器控件
    要创建的控件 WelcomeLabel 是一个简单控件,与标准的 Label 控件类似。WelcomeLabel 类从 WebControl 派生,它定义了一个 Text属性,该属性允许页开发人员提供一个文本字符串,以欢迎访问站点的用户。如果用户名出现在用户浏览器发送的标题中,WelcomeLabel 就会将用户名追加到该文本字符串。有关检索用户名的更多信息,请参见 User。例如,如果页开发人员将“Hello”设置为 Text 属性的值,则根据标题中是否出现用户名,WelcomeLabel 将呈现“Hello, 用户名!”或“Hello!”。

    (二)创建自定义服务器控件的代码
    创建一个名为 WelcomeLabel.cs 的文件。
    将以下代码添加到控件的源文件中:
Option Strict On
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Security.Permissions

' WelcomeLabel.vb
Namespace Samples.AspNet.VB.Controls
    <AspNetHostingPermission(SecurityAction.Demand, _
     Level:=AspNetHostingPermissionLevel.Minimal), _
     AspNetHostingPermission(SecurityAction.InheritanceDemand, _
                            Level:=AspNetHostingPermissionLevel.Minimal), _
                            DefaultProperty("Text"), _
                            ToolboxData("<{0}:WelcomeLabel runat=""server""> </{0}:WelcomeLabel>")> _
        Public Class WelcomeLabel
        Inherits WebControl
        <Bindable(True), _
         Category("Appearance"), _
         DefaultValue(""), _
         Description("The welcome message text."), _
         Localizable(True) _
         > _
                Public Overridable Property Text() As String
            Get
                Dim s As String = CStr(ViewState("Text"))
                If s Is Nothing Then s = String.Empty
                Return s
            End Get
            Set(ByVal value As String)
                ViewState("Text") = value
            End Set
        End Property
        Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
            writer.WriteEncodedText(Text)
            If Context IsNot Nothing Then
                Dim s As String = Context.User.Identity.Name
                If (s IsNot Nothing) AndAlso (s <> String.Empty) Then
                    Dim split() As String = s.Split("\".ToCharArray)
                    Dim n As Integer = split.Length - 1
                    If (split(n) <> String.Empty) Then
                        writer.Write(", ")
                        writer.Write(split(n))
                    End If
                End If
            End If
            writer.Write("!")
        End Sub
    End Class
End Namespace

代码讨论
    下面的代码讨论并不是执行此演练中的步骤必不可少的内容,可以在开始时跳过。但是,如果您初学控件创作,我们建议您至少要在完成演练后阅读此内容。

    如果控件要呈现用户界面 (UI) 元素或任何其他客户端可见的元素,则应从 System.Web.UI.WebControls.WebControl(或派生类)派生该控件。如果控件要呈现在客户端浏览器中不可见的元素(如隐藏元素或 meta 元素),则应从 System.Web.UI.Control 派生该控件。WebControl 类从 Control 派生,并添加了与样式相关的属性,如 Font、ForeColor 和 BackColor。此外,一个从 WebControl 派生的控件也自行参与到 ASP.NET 的主题功能。 如果您的控件要扩展现有控件(如 Button、Label 或 Image 控件)的功能,则可以从该控件派生。由于 WelcomeLabel 扩展了 Label 控件的功能,因此它可从 Label 派生。但是,本演练从 WebControl 派生 WelcomeLabel 以演示如何定义属性和定义属性元数据。

    WelcomeLabel 定义一个 Text 属性,并使用视图状态存储该属性值。使用视图状态保存回发间的 Text 值。每次回发时,将重新创建页并从视图状态还原值。如果 Text 值并未存储在视图状态中,则在每次回发时会将值设置为其默认的 Empty。ViewState 属性继承自 WebControl,是保存数据值的字典。通过使用 String 键,可输入和检索值。本例中将“Text”用作键。字典中的项被类型化为 Object,然后必须将其强制转换为属性类型。
 
    WelcomeLabel 控件通过重写继承的 RenderContents 方法呈现其 Text 属性。传入 RenderContents 方法的参数是 HtmlTextWriter 类型的对象,是具有呈现标记和其他 HTML(和 HTML 变量)标记的方法的实用工具类。

    注意,WelcomeLabel 会连续调用 HtmlTextWriter 对象的 Write 方法,而不是先执行字符串串联然后调用 Write 方法。由于HtmlTextWriter 对象直接写入输出流,因此这样可以提高性能。字符串串联需要时间和内存来创建字符串,然后写入流。在控件中实现呈现时,应按照本演练中说明的模式进行操作。

注意 
    通常,在从 WebControl 派生控件并呈现单个元素时,应重写 RenderContents 方法(而不是 Render 方法),以呈现控件标记中的内容。在呈现控件及其样式属性的开始标记之后,WebControl 的 Render 方法将调用 RenderContents。如果重写 Render 方法以写入内容,则控件将丢失生成到 WebControl 的 Render 方法中的样式呈现逻辑。应用于 WelcomeLabel 的属性包含由公共语言运行库和设计时工具使用的元数据。

在类级别上,通过以下属性标记 WelcomeLabel :
AspNetHostingPermissionAttribute 是代码访问安全属性。该属性使 JIT 编译器检查链接到 WelcomeLabel 的代码是否具有AspNetHostingPermission 权限。所有的公共 ASP.NET 类均使用此属性标记。应将 AspNetHostingPermissionAttribute 应用于控件,以对部分受信任的被调用方进行安全检查。

DefaultPropertyAttribute 是设计时属性 (Attribute),它指定控件的默认属性 (Property)。在可视化设计器中,当页开发人员在设计图面上单击控件时,属性浏览器通常突出显示此默认属性。

ToolboxDataAttribute 指定元素的格式字符串。如果在工具箱中双击控件或将其从工具箱拖动到设计图面上时,该字符串将成为控件的标记。

对于 WelcomeLabel,该字符串创建此元素:

    <aspSample:WelcomeLabel runat="server"> </aspSample:WelcomeLabel>
    WelcomeLabel 控件还从 WebControl 基类继承了两个属性:ParseChildrenAttribute 和 PersistChildrenAttribute。它们被应用为 ParseChildren(true) 和 PersistChildren(false)。这两个属性 (Attribute) 一起与 ToolboxDataAttribute 属性 (Attribute) 共同使用,这样可将子元素解释为属性 (Property),并将属性 (Property) 作为属性 (Attribute) 保留。

以下应用于 WelcomeLabel 的 Text 属性 (Property) 的属性 (Attribute) 是标准设计时属性 (Attribute),通常会将标准设计时属性
(Attribute) 应用于控件的所有公共属性 (Property):

BindableAttribute(被指定为 true 或 false),指定将属性绑定到数据对可视化设计器是否有意义。例如,在 Visual Studio 2005 中,如果属性标记为 Bindable(true),则该属性可显示在“数据绑定”对话框中。如果属性 (Property) 没有使用此属性 (Attribute) 标记,则属性 (Property) 浏览器会推断其值为 Bindable(false)。

CategoryAttribute 指定如何在可视化设计器的属性浏览器中对属性进行分类。例如,当页开发人员使用属性浏览器的分类视图时,Category("Appearance") 将告知属性浏览器在“外观”类别中显示属性。可以根据属性浏览器中的现有类别指定字符串参数,也可以创建自己的类别。

DescriptionAttribute 指定属性的简短描述。在 Visual Studio 2005 中,属性浏览器将在“属性”窗口底部显示选定的属性的描述。

DefaultValueAttribute 指定属性的默认值。此值应与从属性访问器 (getter) 返回的默认值相同。在 Visual Studio 2005 中,DefaultValueAttribute 允许页开发人员通过在“属性”窗口中唤出快捷菜单然后单击“重置”按钮将属性值重置为其默认值。

LocalizableAttribute(指定为 true 或 false)指定本地化属性对可视化设计器是否有意义。当某属性标记为 Localizable(true) 时,可视化设计器会在对本地化资源进行序列化时包含该属性。对控件轮询可本地化的属性时,设计器会将此属性值保存到非特定于区域性的资源文件或其他本地化源中。

注意 
由于 ASP.NET 1.0 版和 1.1 版中的 ASP.NET 本地化模型不同,因此在这些版本中不能将 LocalizableAttribute 应用于自定义服务器控件。
 
    应用于控件及其成员的设计时属性在运行时不会影响控件的功能,但在可视化设计器中使用控件时,这些属性能提升开发人员的体验。有关服务器控件的设计时、分析时和运行时属性的完整列表,可参见自定义服务器控件的元数据属性。

使用 App_Code 目录测试控件(无需编译)
    可以使用 ASP.NET 动态编译功能对页中的控件进行测试,而无需将控件编译为程序集。ASP.NET 能动态编译 ASP.NET 网站根目录下App_Code 目录中放置的代码。这样就可以从页访问 App_Code 中源文件中的类,而无需将其手动编译为程序集。如果将控件的源文件放入了App_Code 目录,则对控件的代码所做的更改能立即在使用这些控件的页中反映出来。
注意 
    App_Code 目录是 ASP.NET 1.0 和 1.1 中都没有的新功能。使用 App_Code 目录进行初始控件测试是一个可选步骤。生成服务器控件的主要步骤与早期版本相同,下一节“将控件编译为程序集”将对此进行介绍。
 
创建 ASP.NET 网站和 App_Code 目录
    创建一个名为 ServerControlsTest 的网站。可以在 IIS 中将该站点创建为名为 ServerControlsTest 的虚拟目录。
直接在网站根目录(也称 Web 应用程序根目录)下创建一个 App_Code 目录。
将控件的源文件(WelcomeLabel.cs 或 WelcomeLabel.vb)复制到 App_Code 目录。

创建标记前缀
    标记前缀是指在页中以声明方式创建控件时出现在控件类型名称前面的前缀,如 <asp:Table /> 中的“asp”。若要在页中以声明方式使用您的控件,则 ASP.NET 需要一个映射到该控件的命名空间的标记前缀。通过在每个使用自定义控件的页上添加一个 @ Register 指令,页面开发人员可提供标记前缀/命名空间映射,如下面的示例所示:

<%@ Register TagPrefix="aspSample"Namespace="Samples.AspNet.VB.Controls"%>
注意 
    ASP.NET 2.0 中的 @ Register 指令与 ASP.NET 1.0 和 ASP.NET 1.1 中的相同。如果您熟悉 ASP.NET 早期版本中的 Register 指令,您会注意到前面的 Register 指令中缺少指定控件程序集名称的 assembly 属性。如果缺少 assembly 属性,则 ASP.NET 会推断该程序集是从App_Code 目录中的源文件动态编译而来。
 
    除了在每个 .aspx 页中使用 @ Register 指令,页面开发人员还可以在 Web.config 文件中指定标记前缀/命名空间映射。如果将在 Web 应用程序的多个页中使用自定义控件,则该方法非常有用。下面的过程描述如何在 Web.config 文件中指定标记前缀映射。

在 Web.config 文件中添加标记前缀映射
如果不存在名为 Web.config 的文本文件,则请在网站的根目录下创建该文件。
创建了新的(空的)Web.config 文件之后,将以下代码复制到该文件中并保存该文件。
<?xml version="1.0"?>
    <configuration>
    <system.web>
    <pages>
    <controls>
           <add tagPrefix="aspSample" namespace="Samples.AspNet.VB.Controls"></add>
    </controls>
    </pages>
    </system.web>
    </configuration>
 
    突出显示部分是一个标记前缀项,该项将标记前缀“aspSample”映射到命名空间Samples.AspNet.VB.Controls。
    如果已存在一个 Web.config 文件,则请将前一步骤中突出显示的文本作为该配置文件的 controls 元素的子项添加到该文件中。如果Web.config 文件中没有 controls 和 pages 元素,则请按照前一步骤中介绍的方法创建这些元素。

注意 
    标记前缀项必须是 controls 节的子项,而该节必须位于 pages 节下,而后者又必须是 system.web 的子项。
在配置文件中指定了标记前缀映射之后,可以在网站的任何页中以声明方式使用 WelcomeLabel 控件(如 <aspSample:WelcomeLabel />)。

注意 
    标记前缀的配置项是ASP.NET 2.0的新功能。在ASP.NET 1.0和1.1中,标记前缀映射在每个使用自定义控件的页的@Register 指令中指定。

创建使用控件的页
创建使用自定义控件的页
在网站中创建一个名为 WelcomeLabelTest.aspx 的网页文件。
将以下标记复制到 WelcomeLabelTest.aspx 文件中并保存该文件。
    <%@ Page Language="VB"%>
     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-

transitional.dtd">
         <html>
          <head id="Head1" runat="server"><title>WelcomeLabel Test</title></head>
           <body><form id="form1" runat="server">
             <div> <aspSample:WelcomeLabel Text="Hello" ID="WelcomeLabel1" runat="server" BackColor="Wheat" ForeColor="SaddleBrown" />
             </div>
                 </form>
             </body>
        </html>
    在地址栏中输入以下 URL,以在浏览器中显示 WelcomeLabelTest.aspx:
http://localhost/ServerControlsTest/WelcomeLabelTest.aspx对控件的源代码做一些更改。例如,通过在 RenderContents 方法末尾处添加此行代码来多写一个字符串:
    writer.Write("Testing how the App_Code directory works.")
    在浏览器中刷新 WelcomeLabelTest.aspx 页。
    将会看到,尽管没有编译控件,对控件所做的更改仍在页中反映出来了。

    除了显式定义的 WelcomeLabel 控件的 Text 属性之外,从页中的控件实例可以看到,它还具有之前并没有定义的 BackColor 和ForeColor 属性。WelcomeLabel 控件通过从 WebControl 基类继承,从而获取与样式相关的这些属性和其他属性。此外,WelcomeLabel 可自行分配外观并成为主题的一部分。

 
发表评论:
 
 
 
Powered by Oblog.