Introduction
Similar controls:
- System.Windows.Forms.DateTimePicker
- gTimePicker
How this control differ:
Features comparison:
|
DateTimePicker |
gTimePicker |
TimeEdit |
| Value Update |
On Mask complete On Lost focus
On validated |
On Lost focus On validated |
Immediately after key press |
Text and Value
is always the same |
No |
No |
Yes |
| Null Value Support |
No |
Yes |
Yes |
could have time only value: like
0001/01/01 01:00 |
No |
Yes |
Yes |
| Has a dropdown clock |
No |
Yes |
In TimeCombo |
It is not needed to use : or arrows
when entering time |
No |
No |
Yes |
Value after key press:
|
DateTimePicker |
gTimePicker |
TimeEdit |
| Example displayed Text |
00:00 |
00:00 |
00:00 |
| Displayed text after pressing [6] Key |
6:00 |
60:00 |
06:00 |
| Value after pressing [6] Key |
00:00 + current date |
00:00 |
06:00 |
| Value after lost focus |
06:00
+ current date
|
06:00 |
06:00 |
Why I Decided to Create It
I need a control that has the following features:
Value property can be set to time only value such as 00:00
(0001/01/01 00:00) witch is the minimum value for DateTime Type
Value property can be DBNull.Value and this is useful for database binding
- Edit time that always it value reflect the displayed text
- Simple time entering by minimum typing
- Could the increase or decrease its value by mouse weal moving or by
arrows pressing
Value Related Property of this Control
- Value (Object): DBNull or WorkingDayDate and Time.
- NullableDateTime (Nullable(of DateTime)): Nothing or WorkingDayDate and Time.
- NullableTime (Nullable(of DateTime)): Nothing or Time.
What This Application Does and Why it is Useful
You could include this control in your application to get the following features:
- Allows your application user to enter a time in 24 hour or 12 hour mode
- Protects your application user from entering invalid time
- If your application check the value of this control it will always
return the right value even before the control lost focus and this is useful
to get the value changing as user typing.
- You could assigned TimeEdit control with a
WorkingDayDateControl to return a date and time in a single property
- It is a simple control and it is inherits from a TextBox and easy to
understand and could be devolved to another more complex control
- It is an alternative and more useable than
DateTimePicker
What Problem is Solved
- When user changes the text of
TimeEdit control, its value changes immediately even if it does not lose focus.
TimeEdit control does not have a MinValue so it could point to time only value.
- It has a
WorkingDayEndTime and WorkingDayDate property that is useful when used in appointment arrangement in a working day that continues after midnight
- It could be assigned to
WorkingDayDateControl to get the date part form it and return the date and time in a single Value property
About TimeCombo and TimeColumn:
Globalization
This control will act the same even if your local culture is differ than en-US. It always use AM PM and : even if your local culture is use others
What the Next Step
- Add a drop down button to display a clock to select time.
- Building an appointment grid to arrange appointments that could be
continue after mid night without break sorting (00:00 will located after
23:59 when sorting by time
Using the Code
- You could
TimeEdit control in your Windows application to mentioned time
- If you build a user control could use
TimeConverter and DateConverter for your control property.
The Demo Application
The demo application comparing between DateTimePicker and TimeEdit control. Ther is 2 TimeEdit control the first one
has WorkingDayEndTime property set to 00:00 and the second TimeEdit control its WorkingDayEndTime is set to 02:00.
When typing in any TimeEdit control or in the DateTimePicker control the value of the control is shown
the date of the second TimeEdit control is set to 0001/01/02 (yyyy/MM/dd) if the time typed is less that WorkingDayEndTime
and this is useful when sorting time in an
appointments arrangements.
It also contains DataGridView that use
TimeColumn.
Points of Interest
How to Keep Value and Text the Same
To do so we don't store the value in a separate variable we use the displayed
text to get the value. and when user is set the value programmatically this
control will study the value:
- If new value is numeric it will considered as Hour; 6.5 will be converted to 06:30
- If new value is DateTime then the
WorkingDayDate property will be set to the new value date and the
NullabeTime property will be set to time part of the new value
- if new value is empty string then value will be
DBNull
- if new value is string that contains time then the value will return its value
Public Overridable Property Value As Object
Get
Try
If String.IsNullOrEmpty(MyBase.Text) Then
Return DBNull.Value
Else
Return Me.NullableDateAndTime.Value
End If
Catch ex As Exception
ErrMsg(ex)
Return DBNull.Value
End Try
End Get
Set(ByVal NewValue As Object)
Try
If IsNumeric(NewValue) Then
Me.NullableTime = (New Date).AddHours(CDbl(NewValue))
ElseIf IsDate(NewValue) Then
Me.NullableDateAndTime = CDate(NewValue)
ElseIf IsDBNull(NewValue) OrElse NewValue Is Nothing Then
Me.Text = ""
ElseIf GetType(TimeSpan).IsAssignableFrom(NewValue.GetType) Then
Me.NullableTime = New Date(CType(NewValue, TimeSpan).Ticks)
ElseIf GetType(String).IsAssignableFrom(NewValue.GetType) Then
If String.IsNullOrEmpty(CStr(NewValue)) Then
Me.Text = ""
Else
Me.NullableTime = ToDateTime(CStr(NewValue))
End If
Else
Me.Text = ""
End If
Catch ex As Exception
ErrMsg(ex)
End Try
End Set
End Property
Validate Time Input and Protecting User from Entering Invalid Time
- Overrides Sub OnKeyPress
- If user press a key in an empty TimeEdit control then it will automatically assign with default value
- Build sText string that echo the user input result
Dim sText = Me.Text
Mid(sText, Me.SelectionStart + 1, 1) = e.KeyChar
- Test if the resulting text is valid Time using Regular Expressions taking
"^(?<Hour>([0-1]\d|2[0-3])):(?<Minute>[0-5]\d)$"
for 24 hour mode and "^(?<Hour>(0?[1-9]|1[0-2])):(?<Minute>[0-5]\d) (?<AMPM>(A|P)M)$" for 12 hour mode
* This Regular Expressions contains three groups Hour, Minute and AMPM
* Each
group has its rule example Hour in 12 hour mode is 0 followed by any digest or 1
followed by 0-2
- If not match then study where the editing char in hours or in minutes and study its possible fixing
as follwing code:
Private Sub OnHourKeyPress(ByRef e As KeyPressEventArgs)
Try
Dim Do1 = False
Select Case SelectionStart
Case 0 Select Case e.KeyChar
Case "3"c To "9"c Do1 = True
Case "2"c If Not _Hr24 Then
Do1 = True
Else
If Me.Text()(1) > "3"c Then
Mid(Me.Text, 2, 1) = "3"
End If
End If
Case "1"c
If Not _Hr24 Then
If Me.Text()(1) > "2"c Then
Mid(Me.Text, 2, 1) = "2"
End If
End If
End Select
Case 1 Select Case MyBase.Text(0)
Case Is > "2"c
If Not Hr24 Then
Do1 = True
End If
Case "2"c
If Me.Hr24 Then
Select Case e.KeyChar
Case "4"c To "9"c
Do1 = True
End Select
Else
Do1 = True
End If
Case "1"c
If Not _Hr24 Then
Select Case e.KeyChar
Case "3"c To "9"c
Do1 = True
End Select
End If
End Select End Select
If Do1 Then
Me.Text = "0" & Me.Text.Substring(1)
SelectionStart = 1
SelectionLength = 1
End If
OnTimeKeyPress(e)
Catch ex As Exception
ErrMsg(ex)
End Try
End Sub
TimeEdit control Inherits
TextBox but it removes some properties by:
- Adding
Designer attribute:
<ToolboxItem(True), Designer(GetType(TimeEditDesigner)), _
DefaultBindingProperty("Value")> _
Public Class TimeEdit
Inherits TextBox
<DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), _
Browsable(False), Obsolete("", True)> _
Public Shadows Lines, Multiline, AutoCompleteMode, _
AutoCompleteSource, AutoCompleteCustomSource, WordWrap, _
PasswordChar, UseSystemPasswordChar As DBNull
End Class
- Building
TimeEditDesigner class:
Imports System.Windows.Forms.Design
Imports System.ComponentModel
Public Class TimeEditDesigner
Inherits ControlDesigner
Protected Overrides Sub PreFilterProperties(ByVal properties As IDictionary)
Try
properties.Remove("PasswordChar")
properties.Remove("UseSystemPasswordChar")
properties.Remove("Text")
properties.Remove("Lines")
properties.Remove("Multiline")
properties.Remove("AutoCompleteMode")
properties.Remove("AutoCompleteSource")
properties.Remove("AutoCompleteCustomSource")
properties.Remove("WordWrap")
MyBase.PreFilterProperties(properties)
Catch ex As Exception
ErrMsg(ex)
End Try
End Sub
Public Overrides ReadOnly Property ActionLists As _
System.ComponentModel.Design.DesignerActionListCollection
Get
Return Nothing
End Get
End Property
Public Overrides ReadOnly Property Verbs As _
System.ComponentModel.Design.DesignerVerbCollection
Get
Return Nothing
End Get
End Property
End Class
How This Application Handle Run Time Errors
Every procedure has the following diagram
Private Sub OnHourKeyPress(ByRef e As KeyPressEventArgs) Try
Catch ex As Exception
ErrMsg(ex)
End Try
End Sub
A module that containing ErrMsg procedure is added to the project to document every run time error happened in a file located in "C:\Temp"
The error is printed to that file using as follows:
FileOpen(iFile, sLogFileName, OpenMode.Append, OpenAccess.Write)
Print(iFile, vbNewLine & vbNewLine & "Date: " _
& Now.ToString("yyyy/MM/dd HH:mm:ss") & vbNewLine)
Print(iFile, sMsg)
FileClose(iFile)
History
- Initial version
- Adding TimeCombo and TimeColumn