最近、暇を見つけては.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値が設定されている状態)
実行例(編集中の状態)
Please give us your valuable comment