Flash 也是网页常用的 ActiveX 插件,在本文中将继承 TBActiveX 下来撰写 TBFlash 控件,用来输出网页套用 Flash 的相关 HTML 码。
程序代码下载:ASP.NET Server Control - Day13.rar
一、网页 Flash 的原始 HTML 码
我们先观查在网页中套用 Flash 插件的原始 HTML 码,以点部落首页抬头的 Flash 原始码为例如下,其中 <object> tag 的 codebase attribute 是指 Flash 插件的下载位置及版本。
<object id="ShockwaveFlash2" height="90" width="728"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0"
classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">
<param value="http://files.dotblogs.com.tw/dotjum/ad/debug.swf" name="movie"/>
<param value="high" name="quality"/>
<param value="#000000" name="bgcolor"/>
<embed height="90" width="728" type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer" quality="high"
src="http://files.dotblogs.com.tw/dotjum/ad/debug.swf"/>
</object>
在 <object> tag 中必要的 attribute 为 classid、codebase、movie、width、height,而 <embed> tag 的必要 attribute 为 src、pluginspage、width、height,其它选择性的 attribute 可参阅以下网页。
Flash OBJECT and EMBED tag attributes
http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_12701
二、实作 TFlash 控件
了解 Flash 的原始 HTML 码后,我们就可以开始着手撰写 TBFlash 控件,想辨法来输出所需要的 HTML 码。
step1. 新增 TBFlash 控件继承至 TBActiveX
我们先在 TBActiveX 控件新增一个 CodeBase 属性,用来设定 ActiveX 插入的下载位置及版本,然后新增 TBFlash 控件继承至 TBActiveX,并在建构函式中设定 MyBase.ClassId 及 MyBase.CodeBase 属性。
Public Class TBFlash
Inherits TBActiveX
''' <summary>
''' 建構函式。
''' </summary>
Sub New()
MyBase.ClassId = "D27CDB6E-AE6D-11CF-96B8-444553540000"
MyBase.CodeBase = "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0"
End Sub
End Class
step2. 加入相关属性
在 TBFlash 加入 MovieUrl 及 Quality 属性,MovieUrl 为 Flash 档案来源,Quality 为影音质量。
step3. 输出 Flash 相关参数
覆写 CreateChildControls 方法,输出 MovieUrl 及 Quality 属性对应的参数,以及在 Params 集合属性设定的参数。
''' <summary>
''' 加入 MediaPlayer 參數。
''' </summary>
''' <param name="Name">參數名稱。</param>
''' <param name="Value">參數值。</param>
Private Sub AddParam(ByVal Name As String, ByVal Value As String)
Dim oParam As TBActiveXParam
oParam = New TBActiveXParam(Name, Value)
Me.Params.Add(oParam)
End Sub
''' <summary>
''' 建立 Embed 標記。
''' </summary>
Private Function CreateEmbed() As HtmlControls.HtmlGenericControl
Dim oEmbed As HtmlControls.HtmlGenericControl
Dim oParam As TBActiveXParam
oEmbed = New HtmlControls.HtmlGenericControl()
oEmbed.TagName = "embed"
oEmbed.Attributes("src") = Me.ResolveClientUrl(Me.MovieUrl)
oEmbed.Attributes("pluginspage") = "http://www.macromedia.com/go/getflashplayer"
oEmbed.Attributes("height") = Me.Height.ToString
oEmbed.Attributes("width") = Me.Width.ToString
'Embed 的 Attributes 加入 Params 集合屬性的設定
For Each oParam In Me.Params
If oParam.Name <> "movie" Then
oEmbed.Attributes(oParam.Name) = oParam.Value
End If
Next
Return oEmbed
End Function
''' <summary>
''' 建立子控制項。
''' </summary>
Protected Overrides Sub CreateChildControls()
Dim oEmbed As HtmlControls.HtmlGenericControl
'加入 movie 參數
AddParam("movie", Me.ResolveClientUrl(Me.MovieUrl))
'加入 quality 參數
If Me.Quality <> EQuality.NotSet Then
AddParam("quality", Me.Quality.ToString.ToLower)
End If
MyBase.CreateChildControls()
oEmbed = CreateEmbed()
Me.Controls.Add(oEmbed)
End Sub
三、测试程序
在页面拖曳 TBFlash 控件,设定 MovieUrl 及 Quality 属性,若有需要加入其它参数,可自行设定 Params 集合属性。执行程序就可以在页面上看到呈现出来的 Flash。
<bee:TBFlash ID="TBFlash1" runat="server" Height="90px"
MovieUrl="http://files.dotblogs.com.tw/dotjum/ad/debug.swf" Quality="High"
Width="728px">
</bee:TBFlash>
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10012267
上篇介绍的 TBActiveX 控件,它可以支持网页 Media Player 的设定,这跟前面提及的 TBMediaPlayer 功能相同。TBActiveX 具有网页设定 ActiveX 通用属性,所以 TBMediaPlayer 基本上是可以由 TBActiveX 继承下来,再加入 Media Player 特有的属性即可。本文将原来的 TBMediaPlayer 控件,继承的父类别由 WebControl 改为 TBActiveX 类别,重新改写 TBMediaPlayer 控件。
程序代码下载:ASP.NET Server Control - Day12.rar
一、改写 TBMediaPlayer 控件
TBMediaPlayer 控件原本是继承 WebControl,现改继承对象为 TBActiveX,来重新改写 TBMediaPlayer 控件。
step1. TBMediaPlayer 继承至 TBActiveX
新增 TBMediaPlayer 控件,继承至 TBActiveX,并在建构函式设定 Media Player ActiveX 的 ClassId。
Public Class TBMediaPlayer
Inherits TBActiveX
''' <summary>
''' 建構函式。
''' </summary>
Sub New()
MyBase.ClassId = "6BF52A52-394A-11D3-B153-00C04F79FAA6"
End Sub
End Class
step2. 加入相关属性
跟原来的 TBMediaPlayer 控件一样,加入 Url、AutoStart、UIMode 三个属性,可视情形加入需要设定的属性。
step3. 加入 Media Player 参数
覆写 CreateChildControls 方法,动态依属性设定在 Params 集合属性加入参数。虽然 TBMediaPlayer 控制项目前只有 Url、AutoStart、UIMode 三个属性,但是父类别 TBActiveX 具有 Params 集合属性,所以开发人员可以视需求加入其它未定义的参数。
''' <summary>
''' 加入 MediaPlayer 參數。
''' </summary>
''' <param name="Name">參數名稱。</param>
''' <param name="Value">參數值。</param>
Private Sub AddParam(ByVal Name As String, ByVal Value As String)
Dim oParam As TBActiveXParam
oParam = New TBActiveXParam(Name, Value)
Me.Params.Add(oParam)
End Sub
''' <summary>
''' 覆寫 CreateChildControls 方法。
''' </summary>
Protected Overrides Sub CreateChildControls()
'加入 Url 參數
If Me.Url <> String.Empty Then
AddParam("URL", Me.ResolveClientUrl(Me.Url))
End If
'加入 autoStart 參數
If Me.AutoStart Then
AddParam("autoStart", "true")
End If
'加入 uiMode 參數
If Me.UIMode <> EUIMode.NotSet Then
AddParam("uiMode", Me.UIMode.ToString)
End If
MyBase.CreateChildControls()
End Sub
二、执行程序
在页面拖曳 TBMediaPlayer 控件,设定 Url、AutoStart、UIMode 属性,若有需要加入其它参数,可自行设定 Params 集合属性。执行程序就可以在页面上看到呈现出来的 Media Player。
<bee:TBMediaPlayer ID="TBMediaPlayer1" runat="server" AutoStart="True"
Height="249px" Url="D:\Movie_01.wmv" Width="250px">
</bee:TBMediaPlayer>
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10012196
Media Player 与 Flash 之类在网页上执行的外挂控件,都是属于 ActiveX 控件,它们套用在 HTML 码中的方式差不多,除了要指定 ClassID 以外,ActiveX 使用的参数(相当于 ActiveX 控件的属性)以 Param Tag 来表示。本文标题命名为「ActiveX 服务器控件」就是避免误解为 ActiveX 控件,而是在 ASP.NET 中输出 ActiveX 相关 HTML 码的服务器控件;我们可透过 ActiveX 服务器控件可以用来输出网页上引用 ActiveX 的通用 HTML 码,另外 ActiveX 的参数会以集合属性来呈现,所以也会一并学习到集合属性的撰写方式。
程序代码下载:ASP.NET Server Control - Day11.rar
一、集合属性
ActiveX 的 Param 参数是集合属性,所以我们定义了 TBActiveParam 类别描述 ActiveX 参数,包含 Name 及 Value 属性;而 TBActiveXParamCollection 为 TBActiveParam 的集合类别,用来描述 ActiveX 参数集合。TBActiveXParamCollection 继承 CollectionBase,加入操作集合的 Add、Insert、Remove、IndexOf、Contains 等方法,关于集合属性的用法可以参阅笔者在部落格的「撰写服务器控件的集合属性 (CollectionBase)」一文中有详细说明。
二、实作 ActiveX 服务器控件
step1. 新增继承 WebControl 的 TBActiveX
step2. 覆写 TagKey 属性,传回 object 的 Tag
Protected Overrides ReadOnly Property TagKey() As HtmlTextWriterTag
Get
Return HtmlTextWriterTag.Object
End Get
End Property
step3. 新增 ClassId 属性,描述 ActiveX 的 ClassId。
定义 ClassId 属性,并覆写 AddAttributesToRender 来输出此属性。
''' <summary>
''' 覆寫 AddAttributesToRender 方法。
''' </summary>
Protected Overrides Sub AddAttributesToRender(ByVal writer As HtmlTextWriter)
'加入 MediaPlayer ActiveX 元件的 classid
writer.AddAttribute("classid", String.Format("clsid:{0}", Me.ClassId))
MyBase.AddAttributesToRender(writer)
End Sub
step4. 新增 Params 属性,描述 ActiveX 的参数集合。
定义 Params 属性,型别为 TBActiveXParamCollection 类别,套用 EditorAttribute 设定 CollectionEditor 为集合编辑器。
''' <summary>
''' ActiveX 控制項參數集合。
''' </summary>
< _
Description("控制項參數集合。"), _
PersistenceMode(PersistenceMode.InnerProperty), _
DesignerSerializationVisibility(DesignerSerializationVisibility.Content), _
Editor(GetType(CollectionEditor), GetType(UITypeEditor)) _
> _
Public ReadOnly Property Params() As TBActiveXParamCollection
Get
If FParams Is Nothing Then
FParams = New TBActiveXParamCollection()
End If
Return FParams
End Get
End Property
当编辑 Params 时,会使用的 CollectionEditor 集合编辑器。
step5. 输出 ActiveX 参数
覆写 CreateChildControls 方法,在此方法依 Params 集合属性定义依序来输出 ActiveX 的参数集合。
Private Sub AddParam(ByVal Name As String, ByVal Value As String)
Dim oParam As HtmlControls.HtmlGenericControl
oParam = New HtmlControls.HtmlGenericControl("param")
oParam.Attributes.Add("name", Name)
oParam.Attributes.Add("value", Value)
Me.Controls.Add(oParam)
End Sub
''' <summary>
''' 建立子控制項。
''' </summary>
Protected Overrides Sub CreateChildControls()
Dim oParam As TBActiveXParam
'加入 ActiveX 參數集合
For Each oParam In Me.Params
AddParam(oParam.Name, oParam.Value)
Next
MyBase.CreateChildControls()
End Sub
三、执行程序
上一篇我们使用 TBMediaPlayer 控件来设定 Media Player,在此我们改用 TBActiveX 控件来设定 Media Player,一样可以呈现相同的结果。
<bee:TBActiveX ID="TBActiveX1" runat="server"
ClassId="6BF52A52-394A-11D3-B153-00C04F79FAA6" Height="250px" Width="250px">
<Params>
<bee:TBActiveXParam Name="URL" Value="d:/Movie_01.wmv" />
<bee:TBActiveXParam Name="autoStart" Value="true" />
</Params>
</bee:TBActiveX>
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10012159
我们在前面几篇文章中,已经简要的对服务器控件做了基本介绍,接下来的几篇文章中我们要开始实作服务器控件。在网页上常使用 Media Player 来拨放影片,在 ASP.NET 中没有现成的控件来处理 Media Player,只能在 aspx 中加入 Media Player 相关的程序代码;本文将示范如何制作一个 Media Player 控件,让我们在 ASP.NET 中更方便的使用 Media Player。
程序代码下载:ASP.NET Server Control - Day10.rar
一、Media Player 原始 HTML 码
在制作 Media Player 控件之前,你需要先了解 Media Player 原本的 HTML 码,控件的作用就是想辨法把这些写在 aspx 中的 HTML 码交由控件来输出而已,以下为网页中加入 Media Player 的 HTML 码范例。
<OBJECT id="VIDEO" width="320" height="240"
style="position:absolute; left:0;top:0;"
CLASSID="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6"
type="application/x-oleobject">
<PARAM NAME="URL" VALUE="your file or url">
<PARAM NAME="SendPlayStateChangeEvents" VALUE="True">
<PARAM NAME="AutoStart" VALUE="True">
<PARAM name="uiMode" value="none">
<PARAM name="PlayCount" value="9999">
</OBJECT>
在下面的网页有 Media Player 相关参数说明。
http://www.mioplanet.com/rsc/embed_mediaplayer.htm
二、实作 Media Player 控件
step1.首先新增由 WebControl 继承下来的 TBMediaPlayer 类别。
Public Class TBMediaPlayer
Inherits WebControl
End Class
step2.覆写 TagKey 属性,传回 object 的 Tag。
Protected Overrides ReadOnly Property TagKey() As System.Web.UI.HtmlTextWriterTag
Get
Return HtmlTextWriterTag.Object
End Get
End Property
step3.输出 HTML Tag 的 Attribute
在 object Tag 中包含 style、classid、type 二个 Attribute,WebControl 本身会处理 style,所以我们只需覆写 AddAttributesToRender 方法,处理 classid 及 type 二个 Attribute,记得覆写 AddAttributesToRender 方法时最后要加入 MyBase.AddAttributesToRender(writer),才会执行父类别的 AddAttributesToRender 方法。
''' <summary>
''' 覆寫 AddAttributesToRender 方法。
''' </summary>
Protected Overrides Sub AddAttributesToRender(ByVal writer As System.Web.UI.HtmlTextWriter)
'加入 MediaPlayer ActiveX 元件的 classid
writer.AddAttribute("classid", "clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6")
writer.AddAttribute("type", "application/x-oleobject")
MyBase.AddAttributesToRender(writer)
End Sub
step4.加入 Url 属性
加入指定播放档案来源的 Url 属性,其中套用 EditorAttribute 设定 UrlEditor,使用 Url 专用的编辑器来设定属性。
''' <summary>
''' 播放檔案來源。
''' </summary>
< _
Description("播放檔案來源"), _
Bindable(True), _
Category("Appearance"), _
Editor(GetType(UrlEditor), GetType(UITypeEditor)), _
UrlProperty(), _
DefaultValue("") _
> _
Public Property Url() As String
Get
Return FUrl
End Get
Set(ByVal value As String)
FUrl = value
End Set
End Property
step5.输出 Url 参数
接下来覆写 CreateChildControls 方法,输出 Url 参数。
''' <summary>
''' 加入參數。
''' </summary>
''' <param name="Name">參數名稱。</param>
''' <param name="Value">參數值。</param>
Private Sub AddParam(ByVal Name As String, ByVal Value As String)
Dim oParam As HtmlControls.HtmlGenericControl
oParam = New HtmlControls.HtmlGenericControl("param")
oParam.Attributes.Add("name", Name)
oParam.Attributes.Add("value", Value)
Me.Controls.Add(oParam)
End Sub
Protected Overrides Sub CreateChildControls()
'加入 Url 參數
AddParam("url", Me.ResolveClientUrl(Me.Url))
MyBase.CreateChildControls()
End Sub
step6.输出 Media Player 其它参数
你可以将 Media Player 的参数设定皆使用相对应的属性来设定,然后使用 step5 的方式来输出所有设定的参数值。
三、Media Player 控件程序代码
Media Player 控件的完整程序代码如下,此控件只加入 URL、AutoStart、UIMode 三个参数,你可以视需求情形将使用到的参数定义为属性来做设定即可。
Public Class TBMediaPlayer
Inherits WebControl
''' <summary>
''' 顯示界面模式。
''' </summary>
Public Enum EUIMode
NotSet
Invisible
None
Mini
Full
End Enum
Private FUrl As String = String.Empty
Private FAutoStart As Boolean = False
Private FUIMode As EUIMode = EUIMode.NotSet
''' <summary>
''' 播放檔案來源。
''' </summary>
< _
Description("播放檔案來源"), _
Bindable(True), _
Category("Appearance"), _
Editor(GetType(UrlEditor), GetType(UITypeEditor)), _
UrlProperty(), _
DefaultValue("") _
> _
Public Property Url() As String
Get
Return FUrl
End Get
Set(ByVal value As String)
FUrl = value
End Set
End Property
''' <summary>
''' 是否自動播放。
''' </summary>
< _
Description("是否自動播放。"), _
DefaultValue(False) _
> _
Public Property AutoStart() As Boolean
Get
Return FAutoStart
End Get
Set(ByVal value As Boolean)
FAutoStart = value
End Set
End Property
''' <summary>
''' 顯示界面模式。
''' </summary>
< _
Description("顯示界面模式。"), _
DefaultValue(GetType(EUIMode), "NotSet") _
> _
Public Property UIMode() As EUIMode
Get
Return FUIMode
End Get
Set(ByVal value As EUIMode)
FUIMode = value
End Set
End Property
Protected Overrides ReadOnly Property TagKey() As System.Web.UI.HtmlTextWriterTag
Get
Return HtmlTextWriterTag.Object
End Get
End Property
''' <summary>
''' 覆寫 AddAttributesToRender 方法。
''' </summary>
Protected Overrides Sub AddAttributesToRender(ByVal writer As System.Web.UI.HtmlTextWriter)
'加入 MediaPlayer ActiveX 元件的 classid
writer.AddAttribute("classid", "clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6")
writer.AddAttribute("type", "application/x-oleobject")
MyBase.AddAttributesToRender(writer)
End Sub
''' <summary>
''' 加入參數。
''' </summary>
''' <param name="Name">參數名稱。</param>
''' <param name="Value">參數值。</param>
Private Sub AddParam(ByVal Name As String, ByVal Value As String)
Dim oParam As HtmlControls.HtmlGenericControl
oParam = New HtmlControls.HtmlGenericControl("param")
oParam.Attributes.Add("name", Name)
oParam.Attributes.Add("value", Value)
Me.Controls.Add(oParam)
End Sub
Protected Overrides Sub CreateChildControls()
'加入 Url 參數
AddParam("URL", Me.ResolveClientUrl(Me.Url))
'加入 autoStart 參數
If Me.AutoStart Then
AddParam("autoStart", "true")
End If
'加入 uiMode 參數
If Me.UIMode <> EUIMode.NotSet Then
AddParam("uiMode", Me.UIMode.ToString)
End If
MyBase.CreateChildControls()
End Sub
End Class
四、执行程序
把 TBMediaPlayer 控件拖曳至页面,设定好属性后,执行程序就可以在页面上看到呈现出来的 Media Player。
<bee:TBMediaPlayer ID="TBMediaPlayer1" runat="server" Height="250px"
Width="250px" Url="~/test.wmv" />
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10012142
接续上篇 Attribute 的介绍,本文将再介绍一些服务器控件常用的 Attribute。
六、ToolboxDataAttribute 类别
作用:指定当自订控件从工具箱拖曳到页面时,为此自订控件产生的预设标记。
当我们新增一个服务器控件,它就会预设在控件类别套用 ToolboxDataAttribute,定义在控件在 aspx 程序代码中的标记。
<ToolboxData("<{0}:TBButton runat=server ></{0}:TBButton>")> _
Public Class TBButton
Inherits System.Web.UI.WebControls.Button
End Class
七、DefaultPropertyAttribute 类别
作用:指定类别的预设属性。
下面的范例中,MyTextbox 类别套用 DefaultPropertyAttribute,设定 Text 属性为预设属性。
<DefaultProperty("Text")> _
Public Class MyTextbox
Inherits WebControl
Public Property Text() As String
Get
Return CType(Me.ViewState("Text"), String)
End Get
Set(ByVal value As String)
Me.ViewState("Text") = value
End Set
End Property
End Class
八、DefaultEventAttribute 类别
作用:指定控件的预设事件。
下面的范例中,MyTextbox 类别套用 DefaultEventAttribute,设定 TextChanged 为预设属性。
<DefaultEvent("TextChanged")> _
Public Class MyTextbox
Inherits WebControl
''' <summary>
''' TextChanged 事件。
''' </summary>
Public Event TextChanged As EventHandler
End Class
当设计阶段在页面上的 MyTextbox 控件点二下时,就会产生预设事件的处理函式。
Protected Sub MyTextbox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyTextbox3.TextChanged
End Sub
九、LocalizableAttribute 类别
作用:指定属性是否应该当地语系化。
当属性套用设为为 true 的 LocalizableAttribute 时,其属性值会储存在资源档中,未来不需修改程序代码就可以将这些资源档当地语系化。
<Localizable(True)> _
Public Property Text() As String
Get
Return CType(Me.ViewState("Text"), String)
End Get
Set(ByVal value As String)
Me.ViewState("Text") = value
End Set
End Property
十、DesignerAttribute 类别
作用:设定控件在设计阶段服务的类别。
指定一个设计阶段的服务类别,来管理控件在设计阶段的行为,例如控件的设计阶段外观、智能标签内容。例如下面范例的 TBGridView 控件就定义了 TBGridViewDesigner 来实作设计阶段的行为,未来的章节中也会介绍如何实作控件的 Designer。
< Designer(GetType(TBGridViewDesigner)) > _
Public Class TBGridView
Inherits GridView
End Class
十一、EditorAttribute 类别
作用:指定在属性窗口中编辑属性值的编辑器。
例如 ListBox 控件的 Items 属性,在属性窗口编辑 Items 属性时,会弹出 Items 集合属性的编辑器。以下范例就是定义 Items 属性的编辑器类别为 TBListItemsCollectionEditor,未来的章节中也会介绍如何实作属性的 Editor。
<Editor(GetType(TBListItemsCollectionEditor), GetType(System.Drawing.Design.UITypeEditor))> _
Public Overrides ReadOnly Property Items() As ListItemCollection
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10012060
Property 与 Attribute 二个术语一般都是翻译成「属性」,例如类别的属性,是使用英文的 Property,而 HTML/XML 的元素属性,使用的英文则是 Attribute。在 .NET 中 Property 与 Attribute 的意义及用法不同,不过微软在线文件也将它翻译为「属性」,这可能让人发生困扰及误解;笔者比较喜欢的方式就是 Property 是属性,Attribute 就维持原文。在 .NET 中类别或属性上可以套用上不同的 Attribute,使类别或属性具有不同的特性,本文将介绍一些在服务器控件常使用到的 Attribute。
一、DescriptionAttribute 类别
作用:指定控件或属性的描述。
当 DescriptionAttribute 套用至控件的类别时,设定的描述内容就会出现在工具箱中控件的提示。
<Description("按鈕控制項")> _
Public Class TBButton
Inherits System.Web.UI.WebControls.Button
End Class
当 DescriptionAttribute 套用至控件的属性时,在属性窗口下面就会出现设定的属性描述内容。
<Description("詢問訊息")> _
Public Property ConfirmMessage() As String
二、DefaultValueAttribute 类别
作用:指定属性的默认值。
使用 DefaultValueAttribute 设定属性的默认值,若设定的属性值与默认值相同时,此属性值就不会出现在 aspx 程序代码中;笔者强烈建议属性一定套用 DefaultValueAttribute,一来在 aspx 中的程序代码会比较少,另外一个重点是若因为某些因素需要修改属性的默认值时,所有已开发页面的控件属性值会一并变更;因为当初属性值是默认值,没有被写入 aspx 程序代码中,所以一但控件的属性默认值变更,页面已布属的控件的属性值就会全面适用。
Private FConfirmMessage As String = String.Empty
<DefaultValue("")> _
Public Property ConfirmMessage() As String
Get
Return FConfirmMessage
End Get
Set(ByVal value As String)
FConfirmMessage = value
End Set
End Property
三、CategoryAttribute 类别
作用:指定属性或事件的分类名称,当属性窗口设定为 [分类] 模式时,以群组方式来显示属性或事件。
例如设定 ConfirmMessage 属性在 "Behavior" 分类,则 ConfirmMessage 属性会被归类到「行为」分类。
<Category("Behavior")> _
Public Property ConfirmMessage() As String
四、BindableAttribute 类别
作用:指定成员是否通常使用于系结。
在数据系结设定窗口中中,指定属性是否预设会出现在属性清单中。
<Bindable(True)> _
Public Property ConfirmMessage() As String
五、BrowsableAttribute 类别
作用:指定属性或事件是否应该在 [属性] 窗口中显示。
若属性在设计阶段无须修正,可以设定该属性不要出现在属性窗口中,此时可以在属性上套用 Browsable(False) 即可。
<Browsable(False)> _
Public Property ConfirmMessage() As String
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10012016
当我们把自订控件加入到工具箱中时,你会发现所有的控件预设都是同样的图标,虽然控件的图标不变更不会有什么影响,不过我们还是希望为自订控件加上合适的外衣,本文将介绍如何设定工具箱控件图标。
一、加入控件图标文件
首先要准备一个 16 x 16 的位图(bmp),如下所示。
将此图文件加入至「服务器控件项目」中,可以如下图所示,用一个特定的数据夹来储存所有工具箱的图示。
然后在图文件的属性窗口中,设定建置动作为「内嵌资源」。
二、设定控件的图标
首先定义一个 TBResource 类别,此为一个空的类别,其命名空间需与根命名空间相同,做为引用资源档时使用。并加上控件图标的 WebResource 定义,因为根命名空间是 Bee.Web,而图档名称为 TBButton.bmp,所以定义如下所示。
假设我们要设定 TBButton 的工具箱图示,则在 TBButton 类别套用 ToolboxBitmapAttribute 如下,其中第一个参数为 GetType(TBResource),第二个参数为图档档名。
重新编辑服务器控件项目,再将 Bee.Web.dll 组件的控件加入工具箱中,你就可以发现 TBButton 的图示已经变成设定的图示了。
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10011933
一般类别的事件撰写很单纯,不过在 ASP.NET 中与前端使用者互动产生的事件就不是那么简单了;在以往的 ASP 年代是没有事件这回事的,而在 ASP.NET 把网页程序撰写真正的对象导向化,客户端使用者的操作透过 PostBack 来产生相对应的事件。例如前端使用者按钮后会引发伺服端 Button 的 Click 事件,当前端使用者输入文字框完毕后离开后会引发伺服端 TextBox 的 TextChanged 事件,在本文中就是要说明如何透过 PostBack 来产生与使用者互动的事件。
一、IPostBackEventHandler 与 IPostBackDataHandler 界面
控件要处理 PostBack 产生的事件,必须实作 IPostBackEventHandler 或 IPostBackDataHandler 接口,这二个接口有什么差别呢?例如 Button 是实作IPostBackEventHandler 接口,由控件产生的 PostBack 直接引发事件,如 Button 的 Click 事件。例如 TextBox 是实作 IPostBackDataHandler 接口,当页面产生 PostBack 时,会传客户端输入的新值给控件,由控件本身去决定是否引发该事件;以 TextBox 举例来说,它会判断新值与旧值不同时才会引发 TextChanged 事件。
二、IPostBackEventHandler 界面实作
首先介绍 IPostBackEventHandler 接口,它包含 RaisePostBackEvent 方法,控件在此方法中需处理要引发那些事件。我们继承 WebControl 撰写 MyButton 类别来说明 IPostBackEventHandler 接口,我们简化控件程序代码直接在 Render 方法输入按钮的 HTML 原始码,并定义一个 Click 事件。实作 IPostBackEventHandler 接口的 RaisePostBackEvent 方法,在此方法中直接引发 Click 事件。
<ToolboxData("<{0}:MyButton runat=server></{0}:MyButton>")> _Public Class MyButton
Inherits WebControl Implements IPostBackEventHandler ''' <summary> ''' Click 事件。 ''' </summary>Public Event Click As EventHandler
''' <summary> ''' 引發 Click 事件。 ''' </summary>Private Sub OnClick(ByVal e As EventArgs)
RaiseEvent Click(Me, e)
End Sub
Public Sub RaisePostBackEvent(ByVal eventArgument As String) Implements System.Web.UI.IPostBackEventHandler.RaisePostBackEvent
Dim e As New EventArgs()
OnClick(e) '引發 Click 事件End Sub
''' <summary> ''' 覆寫 Render 方法。 ''' </summary>Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Dim sHTML As String
sHTML = String.Format("<INPUT TYPE=Submit Name={0} Value = '按鈕'/>", Me.UniqueID)
writer.Write(sHTML)
End Sub
End Class
在页面上拖曳 MyButton 控件,在属性窗口找到 Click 事件,点二下产生 Click 事件处理函式,并撰写测试程序代码如下。
Protected Sub MyButton1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyButton1.Click
Me.Page.Response.Write("MyButton Click 事件")
End Sub
执行程序,当按下 MyButton 按钮时,就会执行它的 RaisePostBackEvent 方法,进而引发 Click 事件,也就会执行 Click 事件处理函式的程序代码。
三、IPostBackDataHandler 界面实作
IPostBackDataHandler 接口包含 LoadPostData 及 RaisePostDataChangedEvent 方法,当页面 PostBack 时,会寻找具 IPostBackDataHandler 接口的控件,先执行LoadPostData 方法,控件在 LoadPostData 方法中会判断客户端传入值决定是否引发事件,若 LoadPostData 传回 True 表示要引发事件,此时会执行RaisePostDataChangedEvent 方法去决定要引发那些事件,反之传回 False 表示不引发事件。
我们继承 WebControl 撰写 MyText 类别来说明 IPostBackDataHandler 接口,我们简化控件程序代码直接在 Render 方法输入文字框的 HTML 原始码,并定义一个 TextChanged 事件。在 LoadPostData 方法中我们会判断客户端传入值与目前的值是否不相同,不相同时才会传回 True,此时才会执行 RaisePostDataChangedEvent 方法,进而引发 TextChanged 事件。
<ToolboxData("<{0}:MyTextbox runat=server></{0}:MyTextbox>")> _Public Class MyTextbox
Inherits WebControl Implements IPostBackDataHandlerPublic Property Text() As String
GetReturn CType(Me.ViewState("Text"), String)
End Get
Set(ByVal value As String)
Me.ViewState("Text") = value
End Set
End Property
''' <summary> ''' TextChanged 事件。 ''' </summary>Public Event TextChanged As EventHandler
''' <summary> ''' 引發 TextChanged 事件。 ''' </summary>Private Sub OnTextChanged(ByVal e As EventArgs)
RaiseEvent TextChanged(Me, e)
End Sub
Public Function LoadPostData(ByVal postDataKey As String, ByVal postCollection As System.Collections.Specialized.NameValueCollection) As Boolean Implements System.Web.UI.IPostBackDataHandler.LoadPostData
'前端使用者輸入值Dim oNewValue As String = postCollection.Item(postDataKey)
If oNewValue <> Me.Text Then
Me.Text = oNewValueReturn True
ElseReturn False
End If
End Function
Public Sub RaisePostDataChangedEvent() Implements System.Web.UI.IPostBackDataHandler.RaisePostDataChangedEvent
Dim e As New EventArgs()
'引發 TextChanged 事件OnTextChanged(e)
End Sub
''' <summary> ''' 覆寫 Render 方法。 ''' </summary>Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Dim sHTML As String
sHTML = String.Format("<INPUT Type=text Name={0} Value={1} >", Me.UniqueID, Me.Text)
writer.Write(sHTML)
End Sub
End Class
在页面上拖曳 MyTextbox 及 MyButton 控件,在 MyButton 的 Click 及 MyTextbox 的 TextChanged 事件撰写如下测试程序代码。
Protected Sub MyButton1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyButton1.Click
Me.Page.Response.Write("MyButton Click 事件")
Me.Page.Response.Write("<br/>")
End Sub
Protected Sub MyTextbox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyTextbox1.TextChanged
Me.Page.Response.Write("MyTextbox TextChanged 事件")
Me.Page.Response.Write("<br/>")
End Sub
执行程序,第一次 MyTextbox 不输入值,直接按下 MyButton,此时只会引发 MyButton Click 事件。
第二次在 MyTextbox 输入 "A",再按下 MyButton,因为 MyTextbox 的值「空字符串->"A"」,所以会引发 MyTextbox 的 TextChanged 事件及 MyButton 的 Click 事件。
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10011861
在 ASP.NET 中,控件的属性与 ViewState 有着密不可分的关系,透过 ViewState 才有辨法维护控件的属性值。在本文中将介绍属性与 ViewState 的关系,并说明属性如何存取 ViewState 是比较有效率的方式。
一、属性与 VIewState
当你加入一个「ASP.NET 服务器控件」时,类别中预设会有一个 Text 属性写法的范例如下所示,属性的读写都是直接存取 ViewState,这是一般常见的控件属性写法。可是这种属性的写法是没有效率的,因为 ViewState 的成员是 Object 型别,每次读取属性时都是由 ViewState 取出指定键值的成员再转型为属性的型别,写入属性的动作也是直接写入 ViewState 中。
Property Text() As String
Get
Dim s As String = CStr(ViewState("Text"))
If s Is Nothing Then
Return String.Empty
Else
Return s
End If
End Get
Set(ByVal Value As String)
ViewState("Text") = Value
End Set
End Property
比较好的方式应该是读取 ViewState 成员只做一次型别转换的动作,而写入 ViewState 的动作可以在 Render 前做批次写入的动作即可。为了达到这样的需求,我们可以覆写 LoadViewState 及 SaveViewState 方法来处理属性与 ViewState 的存取动作;当控件初始化后会执行 LoadViewState 方法,来加载 ViewState 还原的控件状态,当控件 Render 之前,会执行 SaveViewState 方法,将控件的最终状态存入 ViewState 中,也就是在此方法之后对控件所做的任何变更都将会被忽略。
我们改写属性的写法,不直接用 ViewState 来存取属性,而是改用「属性区域变量」来存取属性,在 LoadViewState 时加载 ViewState 到属性区域变量,而 SaveViewState 时再将属性区域变量写入 ViewState 中。我们依此方式将 Text 属性改写如下。
Private FText As String
Property Text() As String
Get
Return FText
End Get
Set(ByVal Value As String)
FText = Value
End Set
End Property
''' <summary>
''' 載入 ViewState 還原控制項狀態。
''' </summary>
Protected Overrides Sub LoadViewState(ByVal savedState As Object)
If Not (savedState Is Nothing) Then
' Load State from the array of objects that was saved at vedViewState.
Dim myState As Object() = CType(savedState, Object())
If Not (myState(0) Is Nothing) Then
MyBase.LoadViewState(myState(0))
End If
If Not (myState(1) Is Nothing) Then
FText = CType(myState(1), String)
End If
End If
End Sub
''' <summary>
''' 將控制項狀態寫入 ViewState 中。
''' </summary>
Protected Overrides Function SaveViewState() As Object
Dim baseState As Object = MyBase.SaveViewState()
Dim myState(1) As Object
myState(0) = baseState
myState(1) = FText
Return myState
End Function
利用上述的方式,我们可以在 LoadViewState 批次加载所有属性值,而在 SaveViewState 批次写入属性值,如此在读取属性就不用一直做型别转换的动作以改善效率。
二、结语
虽然属性一般都是储存于 ViewState 中,不过若是一些无关紧要的属性或是完全不会执行阶段就变更的属性,可以考虑不需要将这些属性储存于 ViewState 中;因为 ViewState 是个两面刃,ViewState 可以很轻易帮我们维护属性值,不过相对的也增加了面页的传输量,所以可以视实际情形来决定属性是否要储存于 ViewState 中。
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10011745
复合控件就是控件可包含其它子控件,复合控件继承至 System.Web.UI.WebControls.CompositeControl,例如 Login 及 Wizard 等控件就是属于复合控件。我们常在网页上常看到一种输入日期的方式是年月日三个下拉列表,本文将利用复合控件来实作这个年月日下拉列表控件,示范如何实作复合控件。
一、CompositeControl 类别的特性
CompositeControl 类别是抽象类别,它会实作 INamingContaner 接口,INamingContaner 接口会在子控件的 ClinetID 加上父控件的 ID,以确保页面上控件的 ClientID 是唯一的。继承 CompositeControl 类别一般都是覆写 CreateChildControls 方法,在此方法中将建立子控件并加入 Controls 集合属性中;当存取其子控件时,若子控件未建立,会执行 CreateChildControls 方法,以会确保所有子控件皆已在存取 ControlCollection 之前建立。
二、日期下拉列表输入器
我们继承 CompositeControl 类别,命名为 TBDropDownDate。这个控件会包含年月日三个下拉列表(DropDownList),所以我们只要在 CreateChildControls 方法中依序建立年月日的 DropDownList 子控件,并加入 Controls 集合属性中即可。
''' <summary>''' 日期下拉清單輸入器。''' </summary>< _
ToolboxData("<{0}:TBDropDownDate runat=server></{0}:TBDropDownDate>") _> _
Public Class TBDropDownDate
Inherits System.Web.UI.WebControls.CompositeControlProtected Overrides Sub CreateChildControls()
Dim oYear As DropDownList
Dim oMonth As DropDownList
Dim oDay As DropDownList
Dim N1 As Integer
'年下拉清單區間為 1950-2010 (年區間可以用屬性來設定) oYear = New DropDownList oYear.ID = "Year"For N1 = 1950 To 2010
oYear.Items.Add(N1.ToString)
NextMe.Controls.Add(oYear) '加入子控制項
Me.Controls.Add(New LiteralControl("年"))
'月下拉清單區間為 1-12 oMonth = New DropDownList oMonth.ID = "Month"For N1 = 1 To 12
oMonth.Items.Add(N1.ToString)
NextMe.Controls.Add(oMonth) '加入子控制項
Me.Controls.Add(New LiteralControl("月"))
'日下拉清單區為為 1-31 oDay = New DropDownList oDay.ID = "Day"For N1 = 1 To 12
oDay.Items.Add(N1.ToString)
NextMe.Controls.Add(oDay) '加入子控制項
Me.Controls.Add(New LiteralControl("日"))
End Sub
End Class
在设定阶段拖曳 TBDropDownDate 到页面上,就可以看到我们在 CreateChildControls 方法中所加入的子控件。
执行程序,检视它的 HTML 原始码,会发现年月日的子控件的 ClientID 都会在原 ID 前加上父控件的 ID,这样命名规则可以确保所有的控件的 ClinetID 都是唯一值。
<span id="TBDropDownDate1">
<select name="TBDropDownDate1$Year" id="TBDropDownDate1_Year">
....省略
<select name="TBDropDownDate1$Month" id="TBDropDownDate1_Month">
....省略
<select name="TBDropDownDate1$Day" id="TBDropDownDate1_Day">
</span>
三、结语
我们已经看过三类服务器控件的简单案例,不过这三个案例都只是简单说明控件 UI 的部分,一个完整的控件需具备属性、方法、事件、设计阶段支持...等,在后面的文章中,我们将陆续针对这些部分做详细的介绍。
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10011633
相对于由无到有开发控件,继承现有现服务器控件是比较简单且实用的方式;若希望在现有的控件增加某些属性或功能,直接继承该控件下来扩展功能是最快的方式,例如「按下 Button 会弹出询问讯息」、「TextBox 设为 ReadOnly 时,可以取得前端传回的 Text 属性」这类需求,都可以直接继承原控件下来,加上我们需要的功能即可。以下我们就以一个简单的案例来说明如何继承现有服务器下来扩展功能。
一、扩展 Button 控件:按钮加上询问讯息
按下按钮执行某些动作前,有时会询问使用者是否执行该动作;例如按下删除钮,会询问使用者是否确定要执行删除的动作。当然这只需要简单的 JavaScript 就可以完成,不过相对于 .NET 的程序语言,JavaScript 是非常不易维护的客户端指令码,如果能让开发人员完全用不到 JavaScript,那何乐不为呢? 那就由 Button 控件本身提供加上询问讯息的功能就可以,相关的 JavaScript 由控件去处理。
一般要在 Button 加上询问讯息,只要在 OnClientClick 属性设定如下的 JavaScript 即可。我们的目的只是让开发人员连设定 OnClientClick 属性的 JavaScript 都省略,直接设定要询问的讯息即可,接下来我们就要开始实作这个控件。
<asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="if (confirm('確定執行嗎?')==false) {return false;}" />
在 Bee.Web 项目中,加入「ASP.NET 服务器控件」,此控件继承 Button 下来命名为 TBButton (命名空间为 Bee.Web.WebControls)。在 TBButton 类别中加入 ConfirmMessage 属性,用来设定询问讯息的内容。然后在 Render 方法将询问询息的 JavaScript 设定到 OnClientClick 属性即可。
Namespace WebControls< _
Description("按鈕控制項"), _ ToolboxData("<{0}:TBButton runat=server></{0}:TBButton>") _> _
Public Class TBButton
Inherits System.Web.UI.WebControls.Button <Description("詢問訊息")> _Public Property ConfirmMessage() As String
GetDim sConfirmMessage As String
sConfirmMessage = CStr(ViewState("ConfirmMessage"))
If sConfirmMessage Is Nothing Then
Return String.Empty
Else Return sConfirmMessageEnd If
End Get
Set(ByVal value As String)
ViewState("ConfirmMessage") = valueEnd Set
End Property
''' <summary> ''' 覆寫 Render 方法。 ''' </summary>Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Dim sScript As String
Dim sConfirm As String
'若有設定 ConfirmMessage 屬性,則在 OnClientClick 加入詢問訊息的 JavaScriptIf Me.ConfirmMessage <> String.Empty Then
sScript = Me.OnClientClick '詢問訊息的 JavaScriptsConfirm = String.Format("if (confirm('{0}')==false) {{return false;}}", Me.ConfirmMessage)
If sScript = String.Empty Then
Me.OnClientClick = sConfirm Else Me.OnClientClick = sConfirm & sScriptEnd If
End If
MyBase.Render(writer)End Sub
End Class
End Namespace
将 TBButton 拖曳到测试页面,设定 ConfirmMessage 属性。
<bee:TBButton ID="TBButton1" runat="server" ConfirmMessage="確定刪除此筆資料嗎?" Text="刪除" />
執行結果如下。
二、结语
笔者在开发 ASP.NET 的应用程序过程中,通常会习惯把所有现有控件继承下来,无论目前需不需要扩展控件功能。这种方式对于开发大型系统是相当有帮助的,因为无法预期在系统开发的过程中会不会因为某些状况,而临时需要扩展控件的功能,所以就先全部继承下来以备不时之需,也为未来保留修改的弹性。
三、相关连结
扩展 CommandField 类别 - 删除提示讯息
按钮加上询问讯息
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10011562
上一篇中已经建立「ASP.NET 服务器控件」项目,接下来我们将学习来撰写第一个服务器控件。
撰写服务器控件大致分为下列三种方式
1.由无到有建立全新的控件,一般会继承至 System.Web.UI.Control 或 System.Web.UI.WebControls.WebControl 类别。
2.继承现有控件,扩展原有控件的功能,如继承原有 TextBox 来扩展功能。
3.复合式控件,将多个现有的控件组合成为一个新的控件,例如 TextBox 右边加个 Button 整合成一个控件,一般会继承至 System.Web.UI.WebControls.CompositeControl 类别。
本文将先介绍第1种方式,由无到有来建立控件,后面的文章中会陆续介绍第2、3种方式的控件。要建立全新的控件会继承至 Control 或 WebControl,没有 UI 的控件可由 Control 继承下来 (如 SqlDataSource),具 UI 的控件会由 WebControl 继承下来。接下来的范例中,我们将继承 WebControl 来建立第一个 MyTextBox 控件。
一、新增 MyTextBox 控件
在 Bee.Web 项目按右键选单,执行「加入\新增项目」,选择「ASP.NET 服务器控件」,在名称文字框中输入 MyTextbox,按下「确定」钮,就会在项目中加入 MyTextbox 控件类别。
新加入的控件预设有一个 Text 属性,以及覆写 RenderContents 方法。RenderContents 方法是「将控件的内容呈现在指定的写入器」,简单的说就是输出控件对应的 HTML 码,用来呈现在客户端的浏览器上。假设我们要撰写一个网页上的文字框,那就先去看一下文字框在网页中对应的 HTML 码,然后在 RenderContents 方法中想辨法输出这些 HTML 码即可。
二、输出控件的 HTML 码
你可以使用 FrontPage 之类的 HTML 编辑器,先编辑出控件的呈现方式,进而去观查它的 HTML 码,再回头去思考如何去撰写这个服务器控件。假设 MyTextbox 控件包含一个文字框及一个按钮,那最终输出的 HTML 码应该如下。
<input id="Text1" type="text" />
<input id="Button1" type="button" value="button" />
我们在 MyTextbox 的 RenderContents 方法中输出上述的 HTML 码。
Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
Dim sHTML As String
sHTML = "<input id=""Text1"" type=""text"" />" & _
"<input id=""Button1"" type=""button"" value=""button"" />"
writer.Write(sHTML)
End Sub
建置控件项目,然后拖曳 MyTextbox 在测试页面上,设计阶段就会呈现出我们期望的结果。
执行程序,在浏览器看一下 MyTextbox 控件输出的结果,是不是跟我们预期的一样呢。
三、属性套用到控件 HTML 码
控件不可能单纯这样输出 HTML 码而已,控件的相关属性设定,一般都影响到输出的 HTML 码。假设 MyTextbox 有 Text 及 ButtonText 二个属性,分别对应到 文字框的内容及按钮的文字,MyTextbox 本来就有 Text 属性,依像画芦葫新增 ButtonText 属性。
< _
Bindable(True), _ Category("Appearance"), _ DefaultValue(""), _ Localizable(True)> _Property ButtonText() As String
GetDim s As String = CStr(ViewState("ButtonText"))
If s Is Nothing Then
Return String.Empty
Else Return sEnd If
End Get
Set(ByVal Value As String)
ViewState("ButtonText") = ValueEnd Set
End Property
RenderContents 方法改写如下。
Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
Dim sHTML As String
sHTML = "<input id=""Text1"" type=""text"" value=""{0}""/>" & _
"<input id=""Button1"" type=""button"" value=""{1}"" />"
sHTML = String.Format(sHTML, Me.Text, Me.ButtonText)
writer.Write(sHTML)
End Sub
重新建置控件项目,在页面上测试 MyTextbox 的 Text 及 ButtonText 属性。
四、使 ClientID (HTML 原始码控件的 ID) 是唯一值
在页面上放置二个 MyTextbox 控件,执行程序,在浏览器中检查 MyTextbox 的 HTML 原始码。你会发现 MyTextbox 会以一个 span 包住控件的内容,而每个控件的输出的 ClientID 是唯一的。不过 MyTextbox 内含的文字框及按钮却会重复,所以一般子控件的 ClientID 会在前面包含父控件的 ID。
<span id="MyTextbox1">
<input id="Text1" type="text" value="這是文字"/>
<input id="Button1" type="button" value="這是按鈕" />
</span>
<br />
<span id="MyTextbox2">
<input id="Text1" type="text" value="這是文字"/>
<input id="Button1" type="button" value="這是按鈕" />
</span>
所以我们再次修改 RenderContents 方法的程序代码。
Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
Dim sHTML As String
sHTML = "<input id=""{0}_Text"" type=""text"" value=""{1}""/>" & _
"<input id=""{0}_Button"" type=""button"" value=""{2}"" />"
sHTML = String.Format(sHTML, Me.ID, Me.Text, Me.ButtonText)
writer.Write(sHTML)
End Sub
执行程序,再次检视 HTML 原始码,所有的 ClinetID 都会是唯一的。
<span id="MyTextbox1">
<input id="MyTextbox1_Text" type="text" value="這是文字"/>
<input id="MyTextbox1_Button" type="button" value="這是按鈕" />
</span>
<br />
<span id="MyTextbox2">
<input id="MyTextbox2_Text" type="text" value="這是文字"/>
<input id="MyTextbox2_Button" type="button" value="這是按鈕" />
</span>
五、控件前置词
自订控件的预设前置词是 cc1,不过这是可以修改的,在项目中的 AssemblyInfo.vb 档案中,加入如下定义即可。详细的作法请参考笔者部落格中的「自订服务器控件前置词」一本有详细介绍,在此不再累述。
'設定控制項的標記前置詞
<Assembly: TagPrefix("Bee.Web.WebControls", "bee")>
六、结语
本文中是用土法炼钢的方法在撰写服务器控件,一般在实作控件时会有更好的方式、更易维护的写法,后续的文章中会陆续介绍相关作法。
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10011523
在 ASP.NET 开发环境中,我们常使用现成的控件直接拖曳至页面中使用,有没有想过我们也可以开发自用的控件呢?本文将本文以 VS2008 为开发工具,VB.NET 为开发程序语言,来说明如何建立「服务器控件」项目,以及如何测试开发阶段的的服务器控件。
一、建立「ASP.NET 服务器控件」项目
首先执行菜单「档案\新增项目」,在项目类型中选择 Visual Basic -> Web,选取「ASP.NET 服务器控件」模板,在名称文字框中输入项目名称,也就是组件的文件名称,我们输入 Bee.Web 为项目名称,组件档案为 Bee.Web.dll,按下「确定」钮即会建立新的「ASP.NET 服务器控件」项目。
在新建立「ASP.NET 服务器控件」项目中,会预设加入一个服务器控件类别(ServerControl1.vb),这个服务器控件已经事件帮我们加入一些控件的程序代码。目前暂不做任何修改,直接使用此控件来做测试说明。
接下来执行菜单「项目\Bee.Web 属性」,设定此组件的根命名空间,一般惯用的根命名空间都会与组件名称相同,以方便加入参考时可以快速找到相关组件。
我们先储存这个「ASP.NET 服务器控件」项目,指定储存位置,按下「储存」钮。整个项目相关档案,会储存在以项目名称的数据夹中。
二、加入测试网站
不要关闭目前「ASP.NET 服务器控件」项目,执行菜单「档案\加入\新网站」,选择「ASP.NET 网站」,会在方案中加入一个网站,来测试开发阶段的服务器控件使用。
在测试网站加入参考,选择「项目」页签,此页签中会列出该方案中其它可加入参考的项目,选取 Bee.Web 项目,按下「确定」钮。
先在 Bee.Web 项目中执行「建置」动作,然后切换到测试网站的页面设计,工具箱中就会出现 ServerControl1 服务器控件。这个控件就可以直接拖曳至页面中使用,这个控件只是单纯 Render 出 Text 属性值,你可以在控件属性窗口中,更改 Text 属性值为 "测试文字",就会看到这个控件显示 "测试文字"。将测试网站设为启动项目,按下「F5」执行程序,就会看到该控制在执行阶段的结果。
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10011408