If you're like me you are not a fan of any "date/time picker" control out there. The UI around them is often clunky or confusing or both. The Telerik radDateTimePicker is about as good as it gets though and for anyone who would like them, here are a few useful tips to make using them just a bit easier.
Keyboard Entry: (My applications use a "/" delimiter for your dates - but any delimiter will work)
Would you like your users to be able to TYPE, "1/1/13"and get "01/01/13" ? How about "020223" to get "02/02/2023" ?
Telerik UI Winforms has an outstanding Mask called "FreeFormDateTime" and this gets us 95% of the way there but it has its quirks (you can type in "2///34234/" if you want. It's not a date and the control is great enough to tell you that but the user can still enter it adding to an ugly UI experience.
Here's how I incorporate FreeFormDateTime mask and still get all of the functionality my users require:
DATE_DELIM illustrates the delimiter my application uses - change it to "-" or "." or whatever your application required. The sample code below references dtpFrom. This is a radDateTimePicker from the UI Winforms library.
Private ConstDATE_DELIM As String= "/"
Private SubFrmDevTest_Load(sender As Object, e AsEventArgs) Handles Me.Load
' I need to capture the keypress, set my masktype and format and clear out the old date value
dtpFrom.DateTimePickerElement.TextBoxElement.MaskType = MaskType.FreeFormDateTime
dtpFrom.Format = DateTimePickerFormat.Custom
dtpFrom.CustomFormat = "MM/dd/yyyy"
dtpFrom.Text = ""
Private SubHandleDateKeyPress(sender As Object, e AsKeyPressEventArgs)
Dimctrl AsRadMaskedEditBoxElement = CType(sender, RadMaskedEditBoxElement)
DimmyChar As Integer= Asc(e.KeyChar)
' If they hit the delimiter key then...what do i do now?
' I know at the end i'll have two delimiters like this:
' mm/dd/yyyy - My application uses a slash but if you want to use something else just change the DATE_DELIM constant.
' If they hit Enter - selection start and length may still be active. Go shut those off
ctrl.TextBoxItem.SelectionStart = ctrl.TextBoxItem.Text.Length
ctrl.TextBoxItem.SelectionLength = 0
' First i need to know where the cursor is - this'll be zero-based
DimCursPos As Integer= ctrl.TextBoxItem.SelectionStart
' I also want to know everythign that's in the textbox
DimCurDateString As String= ctrl.TextBoxItem.Text
' Time to make the donuts.
' Start by looking at the remainder of the CurDateString
' I do this because for now i dont care if i already have the max number of delimiters
DimDateRemaining As String= Mid(CurDateString, CursPos + 1)
' Now look in that remaining string to see if there's already another delimiter present
DimSearchForThis As String= DATE_DELIM
DimFirstCharacter As Integer= DateRemaining.IndexOf(SearchForThis)
DimNextCharacter As Integer= DateRemaining.IndexOf(SearchForThis, FirstCharacter + 1)
IfFirstCharacter = -1 Then
' I didnt find one...so lets count how many delimiters are already present.
' This will determine whether or not to actually add the delimiter
' Just count the parts
DimParts() As String= CurDateString.Split(DATE_DELIM)
DimNumDelims As Integer= Parts.Count
' if i have 3 parts, then i have a mm/dd and yy - dont let them enter any more.
IfNumDelims = 3 Then
e.Handled = True' Ignore the keypress
' We found one...ignore the keypress and move the cursor
e.Handled = True
' Where do i move the cursor to?
DimMoveCursorPos As Integer= (CursPos + FirstCharacter) + 1
' Move it.
ctrl.TextBoxItem.SelectionStart = MoveCursorPos
' How much do i select?
DimSelectLength As Integer
IfNextCharacter = -1 Then
' Select all of the remaining text
SelectLength = (ctrl.TextBoxItem.Text.Length - MoveCursorPos)
' Only select up to the next delimiter
SelectLength = NextCharacter - (FirstCharacter + 1)
' Select it.
ctrl.TextBoxItem.SelectionLength = SelectLength
That's it. Your users will experience a very genuine "Free Form" date entry box with a modicum of enforced rules.
It's SUPER nice to be able to cursor over the DateTimePicker, select the "Month" and start spinning your mouse wheel to scroll up/down the month value. This also works for Day and Year segments in the date....So if this is so great why mention it? Well, it's great and its brutal at the same time. I'll explain:
My applications have forms that do not fit on screen all of the time. This became extremely apparent when COVID rolled over us and we all found ourselves working from home. Most of my users don't have screen resolutions as large as they were enjoying at work. This resulted in me having to ensure my forms would scroll easily for my users without any training. The mouse-wheel was the answer. Everyone already used it for this purpose and its support is practically built into Visual Studio.
The problem is this: When you are scrolling your WinForm using the mouse wheel...and your cursor happens to flow over the top of a radDateTimePicker control - the form STOPS SCROLLING and the radDateTimePicker snatches focus and IT starts to spin its day/month/year value. For a Data-Entry page having dates change on you without knowing it = bad. Having dates change on you to where you have to reload an entire data-structure to fix = bad. Here's how you fix this:
in your form_Load include this:
dtpFrom.DateTimePickerElement.TextBoxElement.EnableMouseWheel = False
There's really no way to have both worlds here - mouse scrolling dates while also allowing mouse-scrolling forms where its possible your users will scroll over the datetimepickers. The dates changing inadvertently was the deciding factor.
I hope this helps folks :)