How can I display a DateTimePicker in a DataGridView?

You haven't missed any built-in option, but it is possible to subclass both the DataGridViewColumn and DataGridViewCell classes to host any control of your choosing.

This article on MSDN explains the process in more detail, and even includes some sample code:
How to: Host Controls in Windows Forms DataGridView Cells

You can also find a complete sample on Code Project: Generic DataGridView V2.0


One strategy would be:

  1. to paint a DateTimePicker on top of the selected cell when it receives focus
  2. hydrate the dtp with the cell's values
  3. when the dtp's value changes, mirror it back into the cell's value
  4. and hide the dtp when the cell loses focus

Here's a way to handle grid events with the laid out strategy:

private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
    // determine if click was on our date column
    if (dataGridView1.Columns[e.ColumnIndex].DataPropertyName == nameof(User.BirthDate))
    {
        // initialize DateTimePicker
        DateTimePicker dtp = new DateTimePicker();
        dtp.Format = DateTimePickerFormat.Short;
        dtp.Visible = true;
        dtp.Value = DateTime.Parse(dataGridView1.CurrentCell.Value.ToString());

        // set size and location
        var rect = dataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
        dtp.Size = new Size(rect.Width, rect.Height);
        dtp.Location = new Point(rect.X, rect.Y);

        // attach events
        dtp.CloseUp += new EventHandler(dtp_CloseUp);
        dtp.TextChanged += new EventHandler(dtp_OnTextChange);

        dataGridView1.Controls.Add(dtp);
    }
}

// on text change of dtp, assign back to cell
private void dtp_OnTextChange(object sender, EventArgs e)
{
    dataGridView1.CurrentCell.Value = dtp.Text.ToString();
}

// on close of cell, hide dtp
void dtp_CloseUp(object sender, EventArgs e)
{
    dtp.Visible = false;
}

And Here's a basic setup for a form that has a DataGridView added to it

private void Form1_Load(object sender, EventArgs e)
{
    // add columns
    var nameCol = new DataGridViewTextBoxColumn(){DataPropertyName = nameof(User.Name),HeaderText = "Name"};
    var dateCol = new DataGridViewTextBoxColumn(){DataPropertyName = nameof(User.BirthDate),HeaderText = "Birthday"};
    dataGridView1.Columns.AddRange(nameCol, dateCol);

    // add data source
    var users = new List<User>()
    {
        new User() {Name = "Briana", BirthDate = new DateTime(2019,10,10)},
        new User() {Name = "Grace", BirthDate = new DateTime(2018,1,18)}
    };
    dataGridView1.DataSource = users;
}

private  DateTimePicker dtp { get; set; }

private class User
{
    public string Name { get; set; }
    public DateTime BirthDate { get; set; }
}

Note: This approach does not currently handle keyboard events when the dtp has focus and also does not handle resizing or repainting if the form moves around