簡単に言うとWebControlを継承し、かつIButtonControlやIPostBackEventHandlerを実装したコントロールなのですが、AppearanceプロパティによりButton/LinkButton/ImageButtonの切り替えが出来ます。
元々はWebControl内でButton/LinkButton/ImageButtonのインスタンスを生成して描画時にAppearanceに応じて描画対象を切り替える作りだったのですが、色々と問題も有ったのでこういった作りに改めました。
ソースはVB.NETのみですが、同様に不便を感じていた方がいらっしゃっいましたら参考になれば幸いです。
Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
''' <summary>
''' 可変ボタンコントロール
''' </summary>
''' <remarks></remarks>
<ToolboxData("<{0}:VariableButton runat=""server"" Text=""VariableButton"" Appearance=""Button"" />"), _
DefaultEvent("Click"), _
DefaultProperty("Text")> _
Public Class VariableButton
Inherits Web.UI.WebControls.WebControl
Implements IButtonControl, IPostBackEventHandler
Public Enum ButtonAppearanceType
LinkButton
Button
ImageButton
End Enum
<Localizable(True), _
Category("Appearance"), _
DefaultValue(""), _
Bindable(True)> _
Public Overridable Property AlternateText() As String
Get
Dim alt As String = CStr(Me.ViewState.Item("AlternateText"))
If Not String.IsNullOrEmpty(alt) Then Return alt
Return String.Empty
End Get
Set(ByVal value As String)
Me.ViewState.Item("AlternateText") = value
End Set
End Property
<Themeable(False), _
DefaultValue(True), _
Category("Behavior")> _
Public Property CausesValidation() As Boolean Implements IButtonControl.CausesValidation
Get
Dim cause As Object = Me.ViewState.Item("CausesValidation")
If Not cause Is Nothing Then Return CBool(cause)
Return True
End Get
Set(ByVal value As Boolean)
Me.ViewState.Item("CausesValidation") = value
End Set
End Property
<Category("Behavior"), _
Themeable(False), _
Bindable(True), _
DefaultValue("")> _
Public Property CommandArgument() As String Implements IButtonControl.CommandArgument
Get
Dim arg As String = CStr(Me.ViewState.Item("CommandArgument"))
If Not String.IsNullOrEmpty(arg) Then Return arg
Return String.Empty
End Get
Set(ByVal value As String)
Me.ViewState.Item("CommandArgument") = value
End Set
End Property
<DefaultValue(""), _
Themeable(False), _
Category("Behavior")> _
Public Property CommandName() As String Implements IButtonControl.CommandName
Get
Dim cmdName As String = CStr(Me.ViewState.Item("CommandName"))
If Not String.IsNullOrEmpty(cmdName) Then Return cmdName
Return String.Empty
End Get
Set(ByVal value As String)
Me.ViewState.Item("CommandName") = value
End Set
End Property
<Category("Layout"), _
DefaultValue(0)> _
Public Overridable Property ImageAlign() As ImageAlign
Get
Dim obj2 As Object = Me.ViewState.Item("ImageAlign")
If (Not obj2 Is Nothing) Then
Return DirectCast(obj2, ImageAlign)
End If
Return ImageAlign.NotSet
End Get
Set(ByVal value As ImageAlign)
If ((value < ImageAlign.NotSet) OrElse (value > ImageAlign.TextTop)) Then
Throw New ArgumentOutOfRangeException("value")
End If
Me.ViewState.Item("ImageAlign") = value
End Set
End Property
<Category("Appearance"), _
UrlProperty(), _
Bindable(True), _
Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", GetType(UITypeEditor)), _
DefaultValue("")> _
Public Overridable Property ImageUrl() As String
Get
Dim url As String = CStr(Me.ViewState.Item("ImageUrl"))
If Not String.IsNullOrEmpty(url) Then Return url
Return String.Empty
End Get
Set(ByVal value As String)
Me.ViewState.Item("ImageUrl") = value
End Set
End Property
<Category("Behavior"), _
NotifyParentProperty(False), _
DefaultValue("")> _
Public Property OnClientClick() As String
Get
Dim script As String = CStr(Me.ViewState.Item("OnClientClick"))
If Not String.IsNullOrEmpty(script) Then Return script
Return String.Empty
End Get
Set(ByVal value As String)
Me.ViewState.Item("OnClientClick") = value
End Set
End Property
<UrlProperty("*.aspx"), _
DefaultValue(""), _
Themeable(False), _
Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", GetType(UITypeEditor)), _
Category("Behavior")> _
Public Property PostBackUrl() As String Implements IButtonControl.PostBackUrl
Get
Dim url As String = CStr(Me.ViewState.Item("PostBackUrl"))
If Not String.IsNullOrEmpty(url) Then Return url
Return String.Empty
End Get
Set(ByVal value As String)
Me.ViewState.Item("PostBackUrl") = value
End Set
End Property
<Bindable(True), _
Localizable(True), _
Category("Appearance"), _
DefaultValue("")> _
Public Property Text() As String Implements IButtonControl.Text
Get
Dim txt As String = CStr(Me.ViewState.Item("Text"))
If Not String.IsNullOrEmpty(txt) Then Return txt
Return String.Empty
End Get
Set(ByVal value As String)
Me.ViewState.Item("Text") = value
End Set
End Property
<Bindable(True), _
Category("Appearance"), _
DefaultValue("Button")> _
Public Property Appearance() As ButtonAppearanceType
Get
Dim typ As Object = Me.ViewState.Item("ButtonAppearanceType")
If Not typ Is Nothing Then Return DirectCast(typ, ButtonAppearanceType)
Return ButtonAppearanceType.Button
End Get
Set(ByVal value As ButtonAppearanceType)
Me.ViewState.Item("ButtonAppearanceType") = value
End Set
End Property
<Themeable(False), _
Category("Behavior"), _
DefaultValue(True)> _
Public Overridable Property UseSubmitBehavior() As Boolean
Get
Dim behaviour As Object = Me.ViewState.Item("UseSubmitBehavior")
If Not behaviour Is Nothing Then Return CBool(behaviour)
Return True
End Get
Set(ByVal value As Boolean)
Me.ViewState.Item("UseSubmitBehavior") = value
End Set
End Property
<DefaultValue(""), _
Themeable(False), _
Category("Behavior")> _
Public Property ValidationGroup() As String Implements IButtonControl.ValidationGroup
Get
Dim vldGroup As String = CStr(Me.ViewState.Item("ValidationGroup"))
If Not String.IsNullOrEmpty(vldGroup) Then Return vldGroup
Return String.Empty
End Get
Set(ByVal value As String)
Me.ViewState.Item("ValidationGroup") = value
End Set
End Property
Public Sub RaisePostBackEvent(ByVal eventArgument As String) Implements IPostBackEventHandler.RaisePostBackEvent
If Me.CausesValidation Then
Me.Page.Validate(Me.ValidationGroup)
End If
RaiseEvent Click(Me, EventArgs.Empty)
RaiseEvent Command(Me, New CommandEventArgs(Me.CommandName, Me.CommandArgument))
End Sub
<Category("Action"), _
Description("Button_OnClick")> _
Public Event Click(ByVal sender As Object, ByVal e As EventArgs) Implements IButtonControl.Click
<Description("Button_OnCommand"), _
Category("Action")> _
Public Event Command(ByVal sender As Object, ByVal e As CommandEventArgs) Implements IButtonControl.Command
Protected Overrides ReadOnly Property TagKey() As HtmlTextWriterTag
Get
Select Case Me.Appearance
Case ButtonAppearanceType.ImageButton
Return HtmlTextWriterTag.Input
Case ButtonAppearanceType.LinkButton
Return HtmlTextWriterTag.A
Case Else
Return HtmlTextWriterTag.Input
End Select
End Get
End Property
Protected Overrides Sub AddAttributesToRender(ByVal writer As HtmlTextWriter)
If Not Me.Page Is Nothing Then Me.Page.VerifyRenderingInServerForm(Me)
If Me.Appearance = ButtonAppearanceType.Button Then
Dim useSubmitBehavior As Boolean = Me.UseSubmitBehavior
If useSubmitBehavior Then
writer.AddAttribute(HtmlTextWriterAttribute.Type, "submit")
Else
writer.AddAttribute(HtmlTextWriterAttribute.Type, "button")
End If
ElseIf Me.Appearance = ButtonAppearanceType.ImageButton Then
writer.AddAttribute(HtmlTextWriterAttribute.Type, "image")
End If