投稿数 - 24, コメント - 191, トラックバック - 26

ASP.NET カスタムコントロール VariableButton

ご無沙汰しています。ひさびさのエントリです。
囚人さんのASP.NET - Button と ImageButton の危ない関係 が元ネタです。

 私もシステムを構築していてButtonからImageButtonやLinkButtonへ変更したい事が多々有り、同様に不便に思っていました。
 元となるHTMLの属性の違いがある為にImageButtonやLinkButtonはButtonコントロールを継承していないだと思いますが、それでも不便に感じていたのでカスタムコントロールを作成して対応していました。

 簡単に言うと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