radianの備忘録

プログラミングやPCに関する事をメモ代わりに残していきます

プロパティの既定値を設定する

カスタムコントロールに独自のプロパティを実装しておくと、Visual Studioのデザイナ画面で値を設定出来るようになって便利です。今回は、フォーカス時に背景色を黄色(LemonChiffon)に変更するTextBoxを考えてみましょう。

Public Class TextBoxEx
    Inherits TextBox

    'フォーカス無し背景色
    Private _NoFocusBackColor As Color = SystemColors.Window

    Protected Overrides Sub InitLayout()
        MyBase.InitLayout()

        '元の背景色を記憶
        _NoFocusBackColor = MyBase.BackColor
    End Sub

    ''' <summary>
    ''' フォーカス時背景色
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <System.ComponentModel.DefaultValue(GetType(Color), "LemonChiffon")> _
    Public Property FocusBackColor As Color = Color.LemonChiffon

    Protected Overrides Sub OnEnter(e As System.EventArgs)
        MyBase.OnEnter(e)

        'フォーカス時背景色を設定
        Me.BackColor = FocusBackColor
    End Sub

    Protected Overrides Sub OnLeave(e As System.EventArgs)
        MyBase.OnLeave(e)

        'フォーカス無し背景色を設定
        Me.BackColor = _NoFocusBackColor
    End Sub

End Class

処理としては、Enter・Leave時にBackColorを設定し直しているだけで、特に難しい所はありません。デザイン画面で設定したBackColorは、InitLayout後にセットされるので、そこで一旦メンバ変数に退避しています。

さて、タイトルにある既定値の設定部分について説明します。

<System.ComponentModel.DefaultValue(GetType(Color), "LemonChiffon")> _
Public Property FocusBackColor As Color = Color.LemonChiffon

DefaultValueは、プロパティの既定値を設定しており、これを設定しておくと、

  • プロパティが既定値の場合、不必要な初期値をソースコードに出力しなくなる
  • デザイン画面でプロパティを右クリックしてリセット出来るようになる。

といった利点があります。ただし、このDefaultValueによる既定値は、定数しか設定出来ないという欠点があります。そのため、Color値を別クラスにして分けるといった事は出来ません。

既定値の設定方法はもう一つあり、それがShouldSerializeメソッド、Resetメソッドを作成する方法です。

ShouldSerialize メソッドと Reset メソッドによる既定値の定義

定数による単純な既定値を設定出来ない場合は、こちらを使用します。FocusBackColorの既定値を、ShouldSerializeメソッドで書き直した例を記述してみます。

Public Property FocusBackColor As Color = Color.LemonChiffon

Private Function ShouldSerializeFocusBackColor() As Boolean
    'Trueを返すとコードに保存する、Falseは保存しない(既定値)
    Return Me.FocusBackColor <> Color.LemonChiffon
End Function

Private Sub ResetFocusBackColor()
    Me.FocusBackColor = Color.LemonChiffon
End Sub

プロパティ名の頭にShouldSerializeを付けたメソッドが既定値かどうかの判定処理、プロパティ名の頭にResetを付けたメソッドが、デザイン画面でリセットを実行した時の処理になります。

ShouldSerializeメソッドを作成する方法は、記述量は少し多くなりますが、比較対象が定数である必要がないので、より柔軟な判定が可能になります。ただし、DefaultValueとの併用は出来ないので注意してください。