I ended up coding a custom control to handle this the right way.
I created a textbox with a button, and added a MonthCalendar control as well.
The textbox+button opens the MonthCalendar control. The only way to choose the datetime now is via the MonthCalendar. You cannot select from the Textbox. I also created a custom event that fires when the date is selected. It works perfectly. Code below:
Public Class CustomDatePicker
'Variables
Friend WithEvents cal As MonthCalendar
Private _isCalendarVisible As Boolean = False
Private _currentSelectedDate As DateTime = Nothing
'Events
Public Event OnDateTimeSet(ByVal sender As Object, ByVal dateValue As DateTime)
Public Event OnDateCleared(ByVal sender As Object)
'Constructor
Public Sub New()
InitializeComponent()
End Sub
'Onload
Private Sub CustomDatePicker_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Initially setup calendar
cal = New MonthCalendar
cal.Name = "Calendar"
cal.MaxSelectionCount = 1
cal.BringToFront()
cal.Location = New Point(Me.Location.X + 5, Me.Location.Y + 25)
Me.Parent.Controls.Add(cal)
cal.Hide()
_isCalendarVisible = False
End Sub
'Returns the currently selected date from the TextBox field
Public ReadOnly Property CurrentSelectedDate()
Get
Return _currentSelectedDate
End Get
End Property
'Display calendar
Private Sub ShowCalendar()
'Close any other custom date controls that are open on the parent form
Dim cont As Control
For Each cont In Parent.Controls
If (cont.GetType().Name = "CustomDatePicker") Then
CType(cont, CustomDatePicker).HideCalendar()
End If
Next
'display the calendar
If Not (_isCalendarVisible) Then
tbxSelectedDate.BackColor = Color.Cornsilk
cal.BringToFront()
cal.Show()
cal.Focus()
_isCalendarVisible = True
btnCalendarToggle.Checked = True
End If
End Sub
'Hide the Calendar
Private Sub HideCalendar()
If (_isCalendarVisible) Then
tbxSelectedDate.BackColor = Color.White
cal.Hide()
_isCalendarVisible = False
btnCalendarToggle.Checked = False
tbxSelectedDate.Focus()
End If
End Sub
'Display the selected datetime into the textbox
Private Sub SetDateTime()
Me.tbxSelectedDate.Text = FormatDateTime(cal.SelectionRange.Start, DateFormat.LongDate)
_currentSelectedDate = FormatDateTime(cal.SelectionRange.Start, DateFormat.LongDate)
RaiseEvent OnDateTimeSet(Me, _currentSelectedDate)
End Sub
'Event when selection is made in the Calendar
Private Sub Calendar_Selection(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DateRangeEventArgs) Handles cal.DateSelected
SetDateTime()
HideCalendar()
End Sub
'Handle the keyboard events associated with the calendar control
Private Sub Calendar_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles cal.KeyPress
If e.KeyChar = ChrW(Keys.Return) Then
SetDateTime()
HideCalendar()
ElseIf e.KeyChar = ChrW(Keys.Escape) Then
HideCalendar()
End If
End Sub
'Handles keypresses on the textbox field
Private Sub tbxSelectedDate_KeyUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles tbxSelectedDate.KeyUp
If (e.KeyCode = Keys.Down) Then
ShowCalendar()
ElseIf (e.KeyCode = Keys.Delete) Then
tbxSelectedDate.Text = ""
End If
End Sub
'Show the calendar when button is clicked
Private Sub btnCalendarToggle_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles btnCalendarToggle.MouseUp
ToggleCalendar()
End Sub
'Show the calendar when button is 'clicked' via ENTER on keyboard
Private Sub btnCalendarToggle_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles btnCalendarToggle.KeyPress
If e.KeyChar = ChrW(Keys.Return) Then
ToggleCalendar()
End If
End Sub
'Toggle calender. If on, turn off. If off, turn on.
Private Sub ToggleCalendar()
If Not (_isCalendarVisible) Then
ShowCalendar()
btnCalendarToggle.Checked = True
Else
HideCalendar()
btnCalendarToggle.Checked = False
End If
End Sub
'When textbox value is changed, check to see if it was cleared. If cleared, raiseevent.
Private Sub tbxSelectedDate_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbxSelectedDate.TextChanged
If (tbxSelectedDate.Text = "") Then
_currentSelectedDate = Nothing
RaiseEvent OnDateCleared(Me)
End If
End Sub