NULLも扱えるDateTimePicker

火曜日 , 28, 7月 2015 Leave a comment

最近、暇を見つけては.NET Frameworkのコントロールの拡張をして遊んでいます。

以前、携わった業務で標準提供されているライブラリではDateTimePickerにNULL値(Nothing)が格納できないということを知りました。
その時は、仕様を作成された方が制約を理解されていたので 、「最大値が入力された場合はNULL値として扱う」という柔軟な対応になったのですが、少し釈然としません。
今回は、その問題を解決するためNULL値も格納できるDateTimePickerを作ってみました。

ValueプロパティがNullable(Of Date)を受け付けるように変更しています。
扱う型を変えてしまっているためValueプロパティをそのままオーバーロードすることはできず、Shadowsで親クラスを隠蔽しています。
あとは、NULL値が入っているときは空文字列を表示、そうではないときは値を親クラスに渡して整形して表示してという流れにして、インスタンス変数_nullを見たりString.IsNullOrEmptyを呼び出したりして、つじつまを合わせています。 

' This software is distributed under the license of NYSL.
' ( http://www.kmonos.net/nysl/ )

'''
''’ NULL値が設定可能なDateTimePicker
'''
Public Class NullableDateTimePicker
    Inherits DateTimePicker

    ''’ NULL値の表示用フォーマット
    Private Const NULL_FORMAT As String = " "

    ''' コンポーネントの入力値がNULL値の場合True
    Private _null As Boolean

    ''' 表示用フォーマット
    Private _customFormat As String

    '''
    '''
    Public Sub New()

        _customFormat = MyBase.CustomFormat
        _null = True
        Me.Format = DateTimePickerFormat.Custom
        Me.Value = Nothing

    End Sub

    Protected Overrides Sub OnPreviewKeyDown(e As System.Windows.Forms.PreviewKeyDownEventArgs)

        Select Case e.KeyCode

            Case Keys.Delete
                ' DELETEで入力値のクリア
                Me.Value = Nothing
                _null = True

            Case Keys.D0 To Keys.D9,
                Keys.NumPad0 To Keys.NumPad9,
                Keys.Up, Keys.Down
                ' 0~9、上下矢印キーの入力で日付入力状態
                If _null Then
                    MyBase.CustomFormat = _customFormat
                    _null = False
                End If

        End Select

        MyBase.OnPreviewKeyDown(e)

    End Sub

    Protected Overrides Sub OnCloseUp(e As EventArgs)

        ' ダイアログを閉じると、値が設定されてしまうので、
        ' その値が表示されるよう、退避していたフォーマットを
        ' セットし、値が表示されるようにする
        MyBase.CustomFormat = _customFormat
        _null = False

        MyBase.OnCloseUp(e)

    End Sub


    '''
    ''' コントロールに設定されている値はNULL値か?
    '''
    '''
    Public Function IsNull() As Boolean
        Return _null
    End Function

#Region "プロパティ"

    '''
    '''
    '''
    '''
    '''
    '''
    Public Shadows Property Value As Nullable(Of Date)
        Get
            If _null Then
                Return Nothing
            End If
            Return MyBase.Value
        End Get

        Set(value As Nullable(Of Date))
            If value Is Nothing Then
                ' Meで設定すると退避していた値を壊してしまうのでMyBaseで設定
                MyBase.CustomFormat = NULL_FORMAT
                _null = True
            Else
                MyBase.Value = value
                Me.CustomFormat = _customFormat
                _null = False
            End If
        End Set
    End Property

    '''
    '''
    '''
    '''
    '''
    '''
    Public Overrides Property Text As String
        Get
            If _null Then
                Return ""
            End If
            Return MyBase.Text
        End Get

        Set(value As String)

            Try

                MyBase.Text = value
                If String.IsNullOrEmpty(Trim(value)) Then
                    ' Meで設定すると退避していた値を壊してしまうのでMyBaseで設定
                    MyBase.CustomFormat = NULL_FORMAT
                    _null = True
                Else
                    Me.CustomFormat = _customFormat
                    _null = False
                End If

            Catch
                ' 例外(System.FormatExceptionなど)が発生した場合はNULL値扱い
                MyBase.Text = ""
                ' Meで設定すると退避していた値を壊してしまうのでMyBaseで設定
                MyBase.CustomFormat = NULL_FORMAT
                _null = True
            End Try

        End Set
    End Property

    '''
    '''
    '''
    '''
    '''
    '''
    Public Shadows Property CustomFormat As String
        Get
            Return _customFormat
        End Get
        Set(value As String)
            ' フォーマットを退避して保持
            _customFormat = value
            ' 親にフォーマットを設定
            MyBase.CustomFormat = value
            ' フォーマットに何らかの文字が入っていればnull状態にはならないはず
            If Not String.IsNullOrEmpty(Trim(value)) Then
                _null = False
            End If
        End Set
    End Property

#End Region

End Class

ソースのダウンロード: NullableDateTimePicker.zip 
(動作確認はVisual Studio 2013 Update 5で行いました。未確認ですが、2010や2015でも動作すると思います。)

以前、公開した和暦表示ができるDateTimePickerの親クラスをSystem.Windows.Forms.DateTimePickerから、今回作成したNullableDateTimePickerに変更した版も作成してみました。

ソースのダウンロード: JpDateTimePicker_r2.zip

値が入った状態
実行例(値が設定されている状態)

Null値が入った状態
実行例(NULL値が設定されている状態)

編集中
実行例(編集中の状態)

Tags:

Please give us your valuable comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください