asp.net

位置:IT落伍者 >> asp.net >> 浏览文章

为ASP.NET控件添加设计时支持


发布日期:2023年02月01日
 
为ASP.NET控件添加设计时支持
Microsoft ASPNET 为开发人员提供了一种适用于 Web 开发的功能最为强大的新工具服务器控件服务器控件使开发人员能够在短时间内开发出响应速度快而且功能强大的 Web 应用程序所需的时间与在典型的 ASP 中创建类似应用程序的时间差不多

ASPNET 服务器控件之所以能够提供生产效率关键原因之一在于它为 Microsoft Visual Studio NET 开发环境中的服务器控件提供了丰富的设计时支持开发人员可以将服务器控件从 Visual Studio NET 工具箱拖放到页面上通过 Properties(属性)窗口访问它们的属性然后在 Visual Studio HTML 编辑器以及 ASPNET 页面的内含代码的类中利用 Microsoft IntelliSense? 语句完成功能这些设计时功能为 Web 开发带来了快速应用程序开发 (RAD) 工具而这些工具已被 Microsoft Visual Basic? 开发人员使用了多年

ASPNET 还使开发人员能够通过创建自定义服务器控件以封装大量可重复使用的用户界面特定的代码(例如登录或注册表单)来进一步提高生产效率尽管开发人员已经开始意识到开发自定义控件的重要性但许多人可能还没有意识到还能在控件中利用 Visual Studio 设计时支持的强大功能使这些控件能够像 ASPNET 中的内置控件那样易于使用本文将介绍 Microsoft NET Framework 和 Visual Studio NET 提供的设计时支持的类型并向开发人员介绍如何构建利用这种支持的控件

设计时支持的类型

针对 Visual Studio NET 中的服务器控件有五种不同的设计时支持它们是

内含代码的类中的 IntelliSense

设计视图中的属性浏览器支持

工具箱支持

HTML 视图中的属性浏览器支持

HTML 编辑器中的 IntelliSense

这些设计时支持类型是由几个不同的机制提供的内含代码的类中的 IntelliSense 由 IDE 启用IDE 为您的控件读取元数据以确定控件所提供的属性和方法及其类型和参数要启用内含代码的类中的 IntelliSense只需对您的控件进行编写和编译然后将其程序集放到使用该控件的应用程序的 bin 子目录中

Visual Studio NET 编辑器设计视图中的属性浏览器支持通过以下两个途径提供将该类型与某个属性相关联和/或将元数据特性与该属性相关联将元数据特性(下文简称为特性)添加到您的代码中用于标识属性的类别提供属性说明以及在需要时指定首选编辑器有些类型的属性(如 SystemDrawingColor)会自动映射到 Visual Studio NET 中的相应编辑器中

Visual Studio NET 的 HTML 视图中的 IntelliSense 和属性浏览器支持通过使用一种 XSD 架构进行提供该架构用于描述与控件相关联的类型它使用称为 Visual Studio 注释的文本修饰指定控件的首选编辑器和其他首选项

最后您可以通过结合特性和带有特定属性的自定义位图来支持从 Visual Studio NET 工具箱拖放控件

Blog 控件示例

用于说明 Visual Studio NET 中的设计时功能的控件称作Blog 控件如本文末尾的列表 所示该控件提供利用 XML 作为存储介质的简单 Web 日志功能Web 日志通常称为 Blog它实际上是一个 Web 页面供人们在上面张贴有关日常生活世态百象时事政治或人们所关心的其他问题的定期观察报告或评论Blog 条目是通过 Web 浏览器添加的

Blog 控件非常简单明了它利用控件组合向浏览器提供输出在组合控件中CreateChildControls 方法(由 ASPNET 运行时自动调用)会被重写利用此方法我们可以创建构成自定义控件 UI 的控件并将它们添加到控件的控件集合中此外该控件还包含用于显示和添加 Blog 以及当 XML Blog 存储文件不存在时创建一个这样的文件的逻辑该控件的几个公共属性需要开发人员在设计时进行设置其中包括在添加新 Blog 时该控件将重定向到的页面的 URL与新 Blog 关联的电子邮件地址控件模式(显示或添加)以及各 Blog 条目之间的分隔线的颜色 所示为正在运行的 Blog 控件Add Blog(添加 Blog)超链接由 ASPNET 超链接控件提供独立于 Blog 控件BlogClientaspx 的代码如列表 所示BlogClientaspx 的 codebehind 类如列表 所示它提供单击 Add Blog(添加 Blog)链接时更改 Blog 模式的逻辑

运行时的 Blog 控件

所示为设计时基本 Blog 控件的外观请注意虽然列出了属性但并未分类

设计时的 Blog 控件

添加设计时支持

虽然在 Web 窗体页上使用 Blog 控件非常简单但并不是很直观例如如果没有相关文档使用 Blog 控件的人就无法知道 Mode 属性的有效值只能是 Display 或 Add如果未将 Add 模式的相关信息明确地告诉使用该控件的开发人员他们就很难自己发现并使用这种模式

对于使用 Visual Studio NET(或支持 IntelliSense 的其他 IDE)的开发人员而言可以通过为控件添加设计时支持来解决这一问题这可以通过综合利用本文前面所介绍的方法来实现在为自定义服务器控件提供设计时支持所面临的挑战中部分原因来自于在自定义控件中全面支持设计时功能所需的方法的多样性最简单的不需要任何附加编码的是内含代码的类中的 IntelliSense 语句完成方法如图 所示此方法适用于 BlogClientaspxvb

内含代码的类中的 IntelliSense

遗憾的是语句完成功能的自动支持并没有扩展到编辑 Web 窗体页时的设计视图或 HTML 视图而且 Visual Studio 也没有提供不需要额外的控件工作就能在属性浏览器中查看和编辑属性的内置支持更复杂的是要在 Web 窗体编辑器的属性浏览器和设计视图中支持 IntelliSense需要采用一种方法要在该编辑器的 HTML 视图中支持 IntelliSense则需要采用另一种方法

要在设计视图中支持属性浏览所需的方法是通过特性告诉 Visual Studio NET 如何处理属性要在 HTML 视图中支持语句完成和属性浏览需要生成一个自定义 XSD 架构以描述控件中的类型我们将在下文讨论这两种方法

设计视图和元数据特性

Visual Studio NET 为使用拖放技术的动态控件设计和修改提供了丰富的支持同时还提供了属性浏览器之类的工具以及相关的设计器(例如颜色选择器)对这些工具的支持是通过一系列特性提供的您可以将这些特性添加到您的控件中这些特性用于告诉 Visual Studio IDE 是否在属性浏览器中显示控件的属性属性所属的类型以及应使用哪个设计器设置属性的值

对于将要提供设计时支持的控件版本我们将制作一份控件文件 Blogvb 的副本并将其命名为 Blog_DTvb然后在副本文件上进行修改这样可以生成该控件的设计时版本并保留原始控件以便进行比较

要支持在属性浏览器中编辑 AddRedirect 属性应在属性进程之前添加以下特性如以下代码片段所示

<Browsable(True) _

Category(行为) _

Description(成功提交新的 Blog 条目后 & _

应重定向到的 & _

页面的 URL) _

Editor(SystemWebUIDesignUrlEditor _

GetType(UITypeEditor))> _

Public Property AddRedirect() As String

属性进程代码

End Property

这些特性声明允许在属性浏览器中显示属性为属性设置所需的类别(当属性按类别排序时)提供属性说明并告诉 Visual Studio NET 使用 UrlEditor 类编辑属性的值如图 所示

设计视图中的属性支持

此处所述的特性语法适用于 Visual Basic NET在 Visual Basic NET 中特性通过以下语法进行声明

<AttributeName(AttributeParams)>

在 C# 中特性采用如下形式

[AttributeName(AttributeParams)]

Visual Basic NET 要求特性声明与其修改的成员位于同一行中因此通常最好在特性后面跟一个 Visual Basic 行接续字符以提高可读性

<AttributeName(AttributeParams)> _

Public Membername()

在 C# 和 Visual Basic 中您可以在一对 [ ] 或 <> 括号中声明多个特性特性之间用逗号分隔而在 Visual Basic NET 中如果它们出现在不同的行中则必须使用 Visual Basic 行接续符衔接特性使其位于同一个语句中

添加工具箱支持

除了设置属性级别的特性外还可设置某些类和程序集级别的特性例如您可以使用程序集级别的特性 TagPrefix 来指定标记前缀供程序集中包含的任何控件使用之后当您从 Visual Studio 工具箱中向某个 Web 窗体页上添加该控件的实例时Visual Studio NET 将自动插入这个标记前缀以下代码片段显示了 TagPrefix 特性的语法该特性应放置在定义该控件的类模块内但应在类和命名空间声明之外(请注意在 Visual Basic NET 项目中命名空间是在项目级别定义的因此您不用担心如何将程序集特性放置到命名空间声明之外)在以下特性中TagPrefix 特性的第一个参数是控件的命名空间第二个参数是您希望为标记前缀使用的文本

<Assembly: TagPrefix(BlogControl BlogControl)>

要将控件集成到 Visual Studio NET 环境中应将 ToolBoxData 特性(该特性用于告诉 Visual Studio NET 从工具箱中为控件插入的首选标记名)添加到实现该控件的类中

<ToolboxData(<{}:Blog_DT runat=server></{}:Blog_DT>)> _

Public Class Blog_DT

Inherits Panel

Implements INamingContainer

控件实现

End Class

将控件从工具箱中插入到页面上时由 TagPrefix 特性指定的标记前缀将插入 {} 占位符而其他文本将按原样插入

您还可以为控件提供自己的自定义图标以显示在工具箱中为此需要创建一个 x 像素大小的位图(左下方的像素采用透明色)其名称与包含该控件的类相同(即 classnamebmp)使用 Add Existing Item(添加现有项)命令将该位图添加到项目中然后使用属性浏览器将其 Build Action(创建操作)设置为 Embedded Resource(内置资源)如图 所示

设置 Build Action(创建操作)

编译完成后该控件将支持从工具箱中将控件添加到某个页面中时为 Blog 控件自动插入 @Register 指令标记前缀和标记名并在工具箱中显示自定义图标如图 所示要将控件添加到 Visual Studio NET 工具箱中应完成以下简单步骤

在设计视图中选择 Visual Studio NET 工具箱的 Web forms(Web 窗体)选项卡

在该选项卡上的任意位置单击鼠标右键然后选择 Add/Remove Items(添加项目/删除项目)(Visual Studio NET 中为 Customize Toolbox [自定义工具箱])

选择 NET Framework Components(NET Framework 组件)选项卡然后单击 Browse(浏览)

浏览到编译后的控件程序集所在的位置选中它并单击 Open(打开)

单击 OK(确定)

工具箱中的自定义控件

将控件添加到工具箱中后可以通过双击该控件或将其从工具箱中拖放到 Web 窗体页上将其添加到 Web 窗体页中无论何种情况Visual Studio NET 都会自动插入正确的 @Register 指令(包括基于程序集级别的特性设置 TagPrefix)还将使用 ToolBoxData 属性中指定的标记名为该控件生成一组标记

添加设计器

正如前文所述Blog 控件在 Web 窗体编辑器的设计视图中没有任何可视界面这使得选择页面上的控件很困难更难以理解控件在运行时的外观为了解决这个问题我们可以添加设计器支持使设计时的 HTML 在外观上接近于运行时的 Blog 控件请注意您还可以生成可以完整再现控件运行时输出的设计器但此操作相当复杂而且超出了本文的讨论范围

所有服务器控件设计器都是从类 SystemWebUIDesignControlDesigner 派生而来该类提供了大量方法您可以重写这些方法为您的控件提供设计时渲染以下代码简单重写了 GetDesignTimeHtml 方法返回设计时显示的简单 HTML请注意该示例显示了 Blog 控件的整个设计器类您可以简单地将其添加到现有的 Blog_DTvb 类文件中

Public Class BlogDesigner

Inherits ControlDesigner

Public Overrides Function GetDesignTimeHtml() As String

Return <h>Blog</h><hr/><hr/>

End Function

End Class

要将该设计器绑定到 Blog_DT 类中我们使用了 Designer 特性如以下片段所示请注意此段代码还添加了一个描述控件功能的 Description 特性

<Description(简单 Blog 控件支持显示 & _

Web 日志/来自 XML 文件的新条目) _

Designer(BlogControlBlogDesigner) _

ToolboxData(<{}:Blog_DT runat=server></{}:Blog_DT>)> _

Public Class Blog_DT

Inherits Panel

Implements INamingContainer

如您所见BlogDesigner 类非常简单但它为控件在 Web 窗体页上的设计时外观添加了大量内容如图 所示

添加设计时渲染

列表 显示了 Blog 控件的代码它已经使用特性进行了更新以启用设计视图和属性浏览器中的控件设计时支持请注意该示例添加了多条 using 指令以导入支持我们使用的特性和设计器类所需要的命名空间这个新列表还添加了一个用于 Mode 属性值的枚举

HTML视图支持自定义架构和 Visual Studio 注释

尽管前文所述的特性帮助我们为 Blog 控件提供了设计时支持但这里遗漏了一个重要的问题在 Web 窗体编辑器的 HTML 视图中添加标记和特性的 IntelliSense 支持对于那些认为在 HTML 环境中工作比在所见即所得风格的环境中工作更舒适的开发人员来说这是一个极大的疏忽

因为 Web 窗体编辑器的 HTML 视图使用 XSD 架构决定在 Web 窗体页上提供哪些元素和特性所以为了纠正这一问题我们需要提供一个描述 Blog 控件及其所支持的特性的 XSD 架构也可以在该架构中添加注释告诉 Visual Studio NET 各种元素的有关信息以及我们所希望的元素行为

列表 包含 Blog 控件特定的 XSD 架构的部分内容实际的架构文件(可从本文的示例代码中获得)还包含面板控件(Blog_DT 控件就是由它派生的)的类型定义以及其他必需的特性和类型定义这些定义是从为内置 ASPNET 服务器控件创建的 aspxsd 架构文件中复制的

请注意任何时候都不应直接修改 aspxsd 架构文件而只应将必需的类型和特性定义复制到您的自定义架构文件中尽管这看起来是多余的但如果直接编辑 aspxsd以后安装 NET Framework 或服务包时该文件将被覆盖您的自定义输入项将因此而丢失

在列表 请注意根架构元素上的 targetNamespace 和 xmlns 特性这两个特性用于为控件的架构定义 XML 命名空间targetNamespace 和 xmlns 特性的值还将用于 Web 窗体页中的特性绑定该架构<xsd:element> 标记定义根 Blog_DT 元素<xsd:complexType> 标记定义 Blog_DT 元素的特性包括 <xsd:attributeGroup> 标记引用的 Web 控件特性最后<xsd:simpleType> 标记定义 BlogMode 类型的枚举该类型被用作 Blog_DT 元素的一个特性

请注意列表 使用 vs:builder 注释来告诉 Visual Studio NET 对 AddRedirect 特性使用 URL 生成器而对 SeparatorColor 特性使用颜色生成器vs:builder 注释是可用于修改架构的注释之一 列出了最常用的注释

常用的 Visual Studio NET 注释

注释用途 有效值 vs:absolutepositioning在根 <schema> 元素上使用用于确定 Visual Studio 是否可以插入用于定位的样式特性true 或 false vs:blockformatted表明是否可以在自动格式化期间为元素添加前导空格true 或 falsevs:builder指定用于编辑相关属性值的生成器颜色样式或 URL vs:deprecated 允许将某个相关属性标记为已否决以防止其在属性浏览器和语句完成中出现true 或 false vs:empty 在元素级别使用用于指示 Visual Studio NET 应对相关标记(无结束标记)使用一个标记语法true 或 falsevs:friendlyname 在根级别使用用于为架构提供显示名 vs:iscasesensitive 在根级别使用说明 Visual Studio NET 是否以区分大小写的方式处理相关标记true 或 false vs:ishtmlschema在根级别使用说明架构是否是一个 HTML 文档架构true 或 false vs:nonbrowseable 在特性级别使用说明该特性不应出现在语句完成中true 或 false vs:readonly 在特性级别使用说明不能在属性窗口中修改该特性true 或 false vs:requireattributequotes 在根级别使用说明特性值必须用引号括起true 或 false

创建自己的 XSD 架构后可以将其与 aspxsd 文件保存到同一位置(在 Visual Studio NET 默认为 C:\Program Files\Microsoft Visual Studio NET \Common\Packages\schemas\xml\)

要允许 Visual Studio NET 读取您的自定义架构需要将一个 xmlns 特性添加到要使用该架构的页面的 <body> 标记中如以下代码片段所示

<body xmlns:BlogControl=urn:/schemas

请注意此段代码使用具有 xmlns 特性的 BlogControl 前缀来说明该架构适用于带有 BlogControl 标记前缀的控件这个可以再次调用的前缀是使用 TagPrefix 特性进行设置的(有关该特性的说明请参见上文中的元数据特性一节)xmlns 特性的值应与架构根元素中定义的 targetNamespace 特性的值相同

通过 xmlns 特性绑定架构之后即可键入一个开放的字符并使 Blog 控件显示为语句完成的一个选项如图 所示此时还应获取已定义属性的语句完成包括 Mode 属性的有效值以及由 XSD 文件中的注释指定的生成器

HTML 视图中的语句完成

小结

本文介绍了 Visual Studio NET 中适用于 ASPNET 服务器控件的设计时支持还说明了开发人员如何在自己的自定义控件中利用这一支持功能虽然在控件中添加设计时支持相对简明但要充分利用这些功能却需要掌握多种不同的技巧特别欠缺的知识领域就是如何将自定义 XSD 架构绑定到页面上在撰写本文时还不具备将页面与控件 XSD 架构连接起来所需的 xmlns 特性的内置支持所以还需要手动添加这个特性希望以后的 Visual Studio NET 版本能够自动完成这一过程

本文中的示例代码包含一个适用于 Blog 控件基础版和设计时支持版的 Visual Studio NET 项目还包含一个说明如何使用每个控件的客户端项目要运行 BlogControlClient 项目您需要在 IIS 中创建一个虚拟目录 BlogControlClient然后将其映射到硬盘驱动器上用于保存 BlogControlClient 项目文件夹的位置

真诚地感谢 Microsoft Visual Studio NET 团队的 Rob Caron他在我编写自定义 XSD 架构的创建和绑定过程中给予了极大的帮助

代码列表

列表 Blogvb

supports Color structure

Imports SystemDrawing

支持 StreamWriter 类型

Imports SystemIO

Imports SystemWebUI

支持使用 HTML 控件

Imports SystemWebUIHtmlControls

支持使用 Web 控件

Imports SystemWebUIWebControls

Public Class Blog

Inherits Panel

Implements INamingContainer

Protected BlogDS As DataSet

Protected TitleTB As TextBox

Protected BlogText As TextBox

Private _addRedirect As String

Private _email As String

Private _mode As String

Private _separatorColor As Color = ColorBlack

Public Property AddRedirect() As String

Get

Return Me_addRedirect

End Get

Set(ByVal Value As String)

Me_addRedirect = Value

End Set

End Property

Public Property Email() As String

Get

Return Me_email

End Get

Set(ByVal Value As String)

Me_email = Value

End Set

End Property

Public Property Mode() As String

Get

Return Me_mode

End Get

Set(ByVal Value As String)

Me_mode = Value

End Set

End Property

Public Property SeparatorColor() As Color

Get

Return Me_separatorColor

End Get

Set(ByVal Value As Color)

Me_separatorColor = Value

End Set

End Property

Protected Overrides Sub OnInit(ByVal e As EventArgs)

LoadData()

MyBaseOnInit(e)

End Sub

Protected Overrides Sub CreateChildControls()

If Not Me_mode = Add Then

DisplayBlogs()

Else

NewBlog()

End If

End Sub

Protected Sub LoadData()

BlogDS = New DataSet()

Try

BlogDSReadXml(PageServerMapPath(Blogxml))

Catch fnfEx As FileNotFoundException

CreateBlankFile()

LoadData()

End Try

End Sub

Protected Sub DisplayBlogs()

Dim BlogDate As DateTime

Dim CurrentDate As DateTime = New DateTime()

Dim BlogRows As DataRowCollection = _

BlogDSTables()Rows

Dim BlogDR As DataRow

For Each BlogDR In BlogRows

Dim BDate As String = BlogDR(date)ToString()

BlogDate = New DateTime _

(ConvertToInt(BDateSubstring( )) _

ConvertToInt(BDateSubstring( )) _

ConvertToInt(BDateSubstring( )))

If Not CurrentDate = BlogDate Then

Dim TempDate As Label = New Label()

TempDateText = BlogDateToLongDateString()

TempDateFontSize = FontUnitLarge

TempDateFontBold = True

MeControlsAdd(TempDate)

MeControlsAdd _

(New LiteralControl(<br/><br/>))

CurrentDate = BlogDate

End If

Dim Anchor As HtmlAnchor = New HtmlAnchor()

AnchorName = # & BlogDR(anchorID)ToString()

MeControlsAdd(Anchor)

Dim Title As Label = New Label()

TitleText = BlogDR(title)ToString()

TitleFontSize = FontUnitLarger

TitleFontBold = True

MeControlsAdd(Title)

MeControlsAdd(New LiteralControl(<p>))

Dim BlogText As LiteralControl = _

New LiteralControl(<div> & _

BlogDR(text)ToString() & </div>)

MeControlsAdd(BlogText)

MeControlsAdd(New LiteralControl(</p>))

Dim Email As HyperLink = New HyperLink()

EmailNavigateUrl = mailto: & _

BlogDR(email)ToString()

EmailText = Email me

MeControlsAdd(Email)

MeControlsAdd(New LiteralControl( | ))

Dim AnchorLink As HyperLink = New HyperLink()

AnchorLinkNavigateUrl = _

PageRequestUrlToString() & # & _

BlogDR(anchorID)ToString()

AnchorLinkText = Link

MeControlsAdd(AnchorLink)

MeControlsAdd(New _

LiteralControl(<hr color= & _

ColorTranslatorToHtml(_separatorColor) & _

width=%/><br/>))

Next

End Sub

Protected Sub NewBlog()

Dim Title As Label = New Label()

TitleText = Create New Blog

TitleFontSize = FontUnitLarger

TitleFontBold = True

MeControlsAdd(Title)

MeControlsAdd(New LiteralControl(<br/><br/>))

Dim TitleLabel As Label = New Label()

TitleLabelText = Title:

TitleLabelFontBold = True

MeControlsAdd(TitleLabel)

TitleTB = New TextBox()

MeControlsAdd(TitleTB)

MeControlsAdd(New LiteralControl(<br/>))

Dim BlogTextLabel As Label = New Label()

BlogTextLabelText = Text:

BlogTextLabelFontBold = True

MeControlsAdd(BlogTextLabel)

BlogText = New TextBox()

BlogTextTextMode = TextBoxModeMultiLine

BlogTextRows =

BlogTextColumns =

MeControlsAdd(BlogText)

MeControlsAdd(New LiteralControl(<br/>))

Dim Submit As Button = New Button()

SubmitText = Submit

AddHandler SubmitClick AddressOf MeSubmit_Click

MeControlsAdd(Submit)

End Sub

Protected Sub Submit_Click(ByVal Sender As Object _

ByVal e As EventArgs)

EnsureChildControls()

AddBlog()

End Sub

Protected Sub AddBlog()

Dim NewBlogDR As DataRow

NewBlogDR = BlogDSTables()NewRow()

NewBlogDR(date) = FormatDate(DateTimeToday)

NewBlogDR(title) = TitleTBText

NewBlogDR(text) = BlogTextText

NewBlogDR(anchorID) = GuidNewGuid()ToString()

NewBlogDR(email) = _email

BlogDSTables()RowsInsertAt(NewBlogDR )

BlogDSWriteXml(PageServerMapPath(Blogxml))

PageResponseRedirect(_addRedirect)

End Sub

Protected Function FormatDate(ByVal dt As DateTime) _

As String

Dim retString As String

retString = StringFormat({:D} dtMonth)

retString &= StringFormat({:D} dtDay)

retString &= StringFormat({:D} dtYear)

Return retString

End Function

Public Sub CreateBlankFile()

Dim NewXml As StreamWriter = _

FileCreateText(PageServerMapPath(Blogxml))

NewXmlWriteLine(<blogs>)

NewXmlWriteLine _

( <! blog field describes a single blog )

NewXmlWriteLine( <blog>)

NewXmlWriteLine( <! date field contains & _

the creation date of the blog )

NewXmlWriteLine( <date> & _

FormatDate(DateTimeToday) & </date>)

NewXmlWriteLine _

( <title>Temporary Blog</title>)

NewXmlWriteLine( <! text field & _

should contain the blog text including any & _

desired HTML tags )

NewXmlWriteLine( <text>This entry & _

indicates that the file blogxml was not & _

foundA default version of this file has & _

been created for youYou can modify the & _

fields in this file as desiredIf you set & _

the Blog control to add mode (add the & _

attribute mode=add to the controls & _

declaration) the control will & _

automatically populate the XML file when & _

you submit the form</text>)

NewXmlWriteLine( <! anchorID field & _

will be autopopulated by the control )

NewXmlWriteLine( <anchorID></anchorID>)

NewXmlWriteLine( <! email field should & _

contain the email address for feedback )

NewXmlWriteLine( <email>change this to a & _

valid email address</email>)

NewXmlWriteLine( </blog>)

NewXmlWriteLine(</blogs>)

NewXmlClose()

End Sub

End Class

列表 BlogClientaspx

<%@ Register TagPrefix=cc Namespace=BlogControl

Assembly=BlogControl %>

<%@ Page Language=vb AutoEventWireup=false

Codebehind=BlogClientaspxvb

Inherits=BlogControlClientWebForm%>

<!DOCTYPE HTML PUBLIC //WC//DTD HTML

Transitional//EN

<html>

<head>

<title>Blog Client</title>

</head>

<body>

<form id=Form method=post runat=server

<p><asp:hyperlink id=Link navigateurl=BlogClientaspx?mode=add runat=server>Add Blog</asp:hyperlink></p>

<cc:blog

id=Blog

Email=

AddRedirect=BlogClientaspx

SeparatorColor=LawnGreen

runat=server></cc:blog>

<p><asp:hyperlink id=Link

navigateurl=BlogClientaspx?mode=add

runat=server>Add Blog</asp:hyperlink></p>

</form>

</body>

</html>

列表 BlogClientaspxvb

Imports BlogControl

Public Class WebForm

Inherits SystemWebUIPage

Protected WithEvents Link As _

SystemWebUIWebControlsHyperLink

Protected WithEvents Link As _

SystemWebUIWebControlsHyperLink

Protected WithEvents Blog As BlogControlBlog

Private Sub Page_Load(ByVal sender As SystemObject _

ByVal e As SystemEventArgs) Handles MyBaseLoad

If RequestQueryString(mode) = add Then

BlogMode = Add

LinkVisible = False

LinkVisible = False

Else

BlogMode = Display

LinkVisible = True

LinkVisible = True

End If

End Sub

End Class

列表 Blog_DTvb

支持设计时特性

Imports SystemComponentModel

支持颜色结构

Imports SystemDrawing

支持 UITypeEditor 类型

Imports SystemDrawingDesign

支持 StreamWriter 类型

Imports SystemIO

Imports SystemWebUI

支持 ControlDesigner 类型

请注意必须添加程序集

SystemDesign 的引用才能导入此命名空间

Imports SystemWebUIDesign

支持使用 HTML 控件

Imports SystemWebUIHtmlControls

支持使用 Web 控件

Imports SystemWebUIWebControls

<Assembly: TagPrefix(BlogControl BlogControl)>

Public Enum BlogMode

Add

Display

End Enum

<Description(Simple Blog controlSupports display & _

of Web log / news items from an XML file) _

Designer(BlogControlBlogDesigner) _

ToolboxData(<{}:Blog_DT runat=server></{}:Blog_DT>)> _

Public Class Blog_DT

Inherits Panel

Implements INamingContainer

Protected BlogDS As DataSet

Protected TitleTB As TextBox

Protected BlogText As TextBox

Private _addRedirect As String

Private _email As String

Private _mode As BlogMode

Private _separatorColor As Color = ColorBlack

<Browsable(True) _

Category(Behavior) _

Description(URL to which the page should redirect after successful submission of a new Blog entry) _

Editor(SystemWebUIDesignUrlEditor _

GetType(UITypeEditor))> _

Public Property AddRedirect() As String

Get

Return Me_addRedirect

End Get

Set(ByVal Value As String)

Me_addRedirect = Value

End Set

End Property

<Browsable(True) _

Category(Behavior) _

Description(Email address the control will use for listing in new Blog entries)> _

Public Property Email() As String

Get

Return Me_email

End Get

Set(ByVal Value As String)

Me_email = Value

End Set

End Property

<Browsable(True) _

Category(Behavior) _

Description(Controls whether existing Blogs are displayed or fields for creating a new Blog entry)> _

Public Property Mode() As BlogMode

Get

Return Me_mode

End Get

Set(ByVal Value As BlogMode)

Me_mode = Value

End Set

End Property

<Browsable(True) _

Category(Appearance) _

Description(Controls the color of the line that separates Blog entries when in display mode)> _

Public Property SeparatorColor() As Color

Get

Return Me_separatorColor

End Get

Set(ByVal Value As Color)

Me_separatorColor = Value

End Set

End Property

Protected Overrides Sub OnInit(ByVal e As EventArgs)

LoadData()

MyBaseOnInit(e)

End Sub

Protected Overrides Sub CreateChildControls()

If Not Me_mode = BlogModeAdd Then

DisplayBlogs()

Else

NewBlog()

End If

End Sub

Protected Sub LoadData()

BlogDS = New DataSet()

Try

BlogDSReadXml(PageServerMapPath(Blogxml))

Catch fnfEx As FileNotFoundException

CreateBlankFile()

LoadData()

End Try

End Sub

Protected Sub DisplayBlogs()

Dim BlogDate As DateTime

Dim CurrentDate As DateTime = New DateTime()

Dim BlogRows As DataRowCollection = _

BlogDSTables()Rows

Dim BlogDR As DataRow

For Each BlogDR In BlogRows

Dim BDate As String = BlogDR(date)ToString()

BlogDate = New DateTime _

(ConvertToInt(BDateSubstring( )) _

ConvertToInt(BDateSubstring( )) _

ConvertToInt(BDateSubstring( )))

If Not CurrentDate = BlogDate Then

Dim TempDate As Label = New Label()

TempDateText = BlogDateToLongDateString()

TempDateFontSize = FontUnitLarge

TempDateFontBold = True

MeControlsAdd(TempDate)

MeControlsAdd _

(New LiteralControl(<br/><br/>))

CurrentDate = BlogDate

End If

Dim Anchor As HtmlAnchor = New HtmlAnchor()

AnchorName = # + BlogDR(anchorID)ToString()

MeControlsAdd(Anchor)

Dim Title As Label = New Label()

TitleText = BlogDR(title)ToString()

TitleFontSize = FontUnitLarger

TitleFontBold = True

MeControlsAdd(Title)

MeControlsAdd(New LiteralControl(<p>))

Dim BlogText As LiteralControl = _

New LiteralControl(<div> & _

BlogDR(text)ToString() & </div>)

MeControlsAdd(BlogText)

MeControlsAdd(New LiteralControl(</p>))

Dim Email As HyperLink = New HyperLink()

EmailNavigateUrl = mailto: & _

BlogDR(email)ToString()

EmailText = Email me

MeControlsAdd(Email)

MeControlsAdd(New LiteralControl( | ))

Dim AnchorLink As HyperLink = New HyperLink()

AnchorLinkNavigateUrl = _

PageRequestUrlToString() & # & _

BlogDR(anchorID)ToString()

AnchorLinkText = Link

MeControlsAdd(AnchorLink)

MeControlsAdd _

(New LiteralControl(<hr color= & _

ColorTranslatorToHtml(_separatorColor) & _

width=%/><br/>))

Next

End Sub

Protected Sub NewBlog()

Dim Title As Label = New Label()

TitleText = Create New Blog

TitleFontSize = FontUnitLarger

TitleFontBold = True

MeControlsAdd(Title)

MeControlsAdd(New LiteralControl(<br/><br/>))

Dim TitleLabel As Label = New Label()

TitleLabelText = Title:

TitleLabelFontBold = True

MeControlsAdd(TitleLabel)

TitleTB = New TextBox()

MeControlsAdd(TitleTB)

MeControlsAdd(New LiteralControl(<br/>))

Dim BlogTextLabel As Label = New Label()

BlogTextLabelText = Text:

BlogTextLabelFontBold = True

MeControlsAdd(BlogTextLabel)

BlogText = New TextBox()

BlogTextTextMode = TextBoxModeMultiLine

BlogTextRows =

BlogTextColumns =

MeControlsAdd(BlogText)

MeControlsAdd(New LiteralControl(<br/>))

Dim Submit As Button = New Button()

SubmitText = Submit

AddHandler SubmitClick AddressOf MeSubmit_Click

MeControlsAdd(Submit)

End Sub

Protected Sub Submit_Click(ByVal Sender As Object _

ByVal e As EventArgs)

EnsureChildControls()

AddBlog()

End Sub

Protected Sub AddBlog()

Dim NewBlogDR As DataRow

NewBlogDR = BlogDSTables()NewRow()

NewBlogDR(date) = FormatDate(DateTimeToday)

NewBlogDR(title) = TitleTBText

NewBlogDR(text) = BlogTextText

NewBlogDR(anchorID) = GuidNewGuid()ToString()

NewBlogDR(email) = _email

BlogDSTables()RowsInsertAt(NewBlogDR )

BlogDSWriteXml(PageServerMapPath(Blogxml))

PageResponseRedirect(_addRedirect)

End Sub

Protected Function FormatDate(ByVal dt As DateTime) As String

Dim retString As String

retString = StringFormat({:D} dtMonth)

retString &= StringFormat({:D} dtDay)

retString &= StringFormat({:D} dtYear)

Return retString

End Function

Public Sub CreateBlankFile()

Dim NewXml As StreamWriter = _

FileCreateText(PageServerMapPath(Blogxml))

NewXmlWriteLine(<blogs>)

NewXmlWriteLine _

( <! blog field describes a single blog )

NewXmlWriteLine( <blog>)

NewXmlWriteLine( <! date field contains & _

the creation date of the blog )

NewXmlWriteLine( <date> & _

FormatDate(DateTimeToday) & </date>)

NewXmlWriteLine _

( <title>Temporary Blog</title>)

NewXmlWriteLine( <! text field & _

should contain the blog text including any & _

desired HTML tags )

NewXmlWriteLine( <text>This entry & _

indicates that the file blogxml was not & _

foundA default version of this file has & _

been created for youYou can modify the & _

fields in this file as desiredIf you set & _

the Blog control to add mode (add the & _

attribute mode=add to the controls & _

declaration) the control will & _

automatically populate the XML file when & _

you submit the form</text>)

NewXmlWriteLine( <! anchorID field & _

will be autopopulated by the control )

NewXmlWriteLine( <anchorID></anchorID>)

NewXmlWriteLine( <! email field should & _

contain the email address for feedback )

NewXmlWriteLine( <email>change this to a & _

valid email address</email>)

NewXmlWriteLine( </blog>)

NewXmlWriteLine(</blogs>)

NewXmlClose()

End Sub

End Class

Public Class BlogDesigner

Inherits ControlDesigner

Public Overrides Function GetDesignTimeHtml() As String

Return <h>Blog</h><hr/><hr/>

End Function

End Class

列表 Blogxsd

<?xml version= encoding=utf ?>

<xsd:schema

targetNamespace=urn:/schemas

elementFormDefault=qualified

xmlns=urn:/schemas

xmlns:xsd=

xmlns:vs=StudioIntellisense

vs:friendlyname=Blog Control Schema

vs:ishtmlschema=false

vs:iscasesensitive=false

vs:requireattributequotes=true

<xsd:annotation>

<xsd:documentation>

Blog Control schema

</xsd:documentation>

</xsd:annotation>

<xsd:element name=Blog_DT type=BlogDef />

<! <aspnetian:Blog>

<xsd:complexType name=BlogDef

<! <aspnetian:Blog>specific attributes

<xsd:attribute name=AddRedirect type=xsd:string

vs:builder=url/>

<xsd:attribute name=Email type=xsd:string/>

<xsd:attribute name=Mode type=BlogMode/>

<xsd:attribute name=SeparatorColor

type=xsd:string

vs:builder=color/>

<! <asp:Panel>specific attributes

<xsd:attribute name=BackImageUrl

type=xsd:anyURI />

<xsd:attribute name=HorizontalAlign

type=HorizontalAlign />

<xsd:attribute name=Wrap type=xsd:boolean />

<xsd:attribute name=Enabled type=xsd:boolean />

<xsd:attribute name=BorderWidth type=ui />

<xsd:attribute name=BorderColor type=xsd:string

vs:builder=color />

<xsd:attribute name=BorderStyle

type=BorderStyle />

<xsd:attributeGroup ref=WebControlAttributes />

</xsd:complexType>

<! DataTypes

<xsd:simpleType name=BlogMode

<xsd:restriction base=xsd:string

<xsd:enumeration value=Add />

<xsd:enumeration value=Display />

</xsd:restriction>

</xsd:simpleType>

</xsd:schema>

               

上一篇:ASP.NET Starter Kit开始 Web 站点开发

下一篇:Asp.Net中NHiernate的Session的管理