Search code examples
c#winformsdatetimepicker

C#: DateTimePicker has dropdown display errors on program startup at low width with custom format. What is causing this?


DateTimePicker has a calendar drop-down button on its right side. Usually it displays a little calendar icon, but if the control is resized to the point where the icon would overlap the text, it changes to a thinner arrow dropdown.

The problem: If the DateTimePicker is below that width when the program is launched, the dropdown icon is very wide and overlaps the text. Resizing the window horizontally corrects the width, and after that it stays corrected.

I would like to know:

  1. What is causing this.
  2. How best to fix it.

Here's what it looks like:

On Launch

DateTimePicker Control on startup. The dropdown icon is too wide.

After Resize

DateTimePicker Control after resizing. The dropdown icon is just right.

Edit #1:

This display issue only seems to happen on startup. If I add a new control based on user input it displays properly:

Animation of DateTimePicker bug in action.

Edit #2:

I've further narrowed down what's causing the issue. It only occurs (on my PC, running Windows 8.1) when:

  • The DateTimePicker.Format is set to 'Custom'.
  • The DateTimePicker's width at startup is set to 109 or wider.
  • The right edge of the control is close enough to the formatted date that its icon collapses down to the arrow dropdown.

If I set the control's custom format to "MMMM d, yyyy", I get the issue. This formatting is exactly the same as when DateTimePicker.Format is set to 'Long', but without a custom format the control displays properly.


Solution

  • As Hans pointed out in the comments above:

    It is just a plain bug, nothing you can do about it because it is baked into the OS.

    This answers the first part of the question, and means that we're stuck working around it. This leaves a few options:

    1. Make the control big enough at startup. This requires you to be mindful of the bug as you lay out the form, but it's simple and it works.
    2. Wait until after the form has loaded to add the controls, using Form.Load. This solution is set and forget, but involves modifying the form object itself which might not work for everyone.

    Option 2 worked well for my purposes. The code looks something like this:

    public class EventForm : Form
    {
        public EventForm()
        {
            this.Load += AddControls;
        }
    
        private void AddControls (object sender, EventArgs e)
        {
            DateTimePicker startDate = new DateTimePicker();
            startDate.Format = DateTimePickerFormat.Custom;
            startDate.CustomFormat = "MMM dd, yyyy — h:mm tt";
            startDate.Dock = DockStyle.Top;
    
            this.Controls.Add(startDate);
            // Add the rest of your controls here.
        }
    }
    

    I'm not sure whether there are any drawbacks to this method, but I'm sure I'll find out soon if there is.

    Other answers are appreciated, as is feedback. For now I'm going to mark this as the answer; hopefully it helps someone down the road!