.net 如何在 DataGridView 中显示 DateTimePicker?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4815677/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I display a DateTimePicker in a DataGridView?
提问by Furqan Sehgal
Is there any way to put a DateTimePicker control in the DataGridView?
有没有办法在 DataGridView 中放置一个 DateTimePicker 控件?
I checked all the possible properties but it give option of checkbox, combo box etc, but not the DateTimePicker.
我检查了所有可能的属性,但它提供了复选框、组合框等选项,但没有提供 DateTimePicker。
回答by Cody Gray
You haven't missed any built-in option, but it is possible to subclass both the DataGridViewColumnand DataGridViewCellclasses to host any control of your choosing.
您没有错过任何内置选项,但是可以将DataGridViewColumn和DataGridViewCell类都子类化以承载您选择的任何控件。
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
MSDN 上的这篇文章更详细地解释了该过程,甚至包括一些示例代码:
How to: Host Controls in Windows Forms DataGridView Cells
You can also find a complete sample on Code Project: Generic DataGridView V2.0
您还可以在代码项目中找到完整示例:Generic DataGridView V2.0
回答by rajat
One strategy would be:
一种策略是:
- to paint a
DateTimePickeron top of the selected cell when it receives focus - hydrate the dtp with the cell's values
- when the dtp's value changes, mirror it back into the cell's value
- and hide the dtp when the cell loses focus
DateTimePicker在选定单元格接收焦点时在其顶部绘制 a- 用单元格的值对 dtp 进行水合
- 当 dtp 的值发生变化时,将其镜像回单元格的值
- 并在单元格失去焦点时隐藏 dtp
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
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
这是添加了 DataGridView 的表单的基本设置
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
注意:当 dtp 具有焦点时,此方法当前不处理键盘事件,并且如果表单四处移动,也不处理调整大小或重新绘制
回答by Aaron Webb
Maybe this isn't proper, but easy trick and same result........ lot less code......I was just playing around and though outside the box, just set
也许这不合适,但简单的技巧和相同的结果......更少的代码......我只是在玩,虽然在盒子外面,只是设置
I hide mine until they click cell, or you can show First I declared :
我隐藏我的,直到他们点击单元格,或者你可以显示我首先声明:
DateTimePicker1.Visible = False
when you click in cell, run this code...
当您单击单元格时,运行此代码...
DateTimePicker1.Visible = True
ActiveControl = DateTimePicker1
Then below
那么下面
Public Sub DateTimePicker1_ValueChanged(sender As System.Object, e As System.EventArgs) Handles DateTimePicker1.ValueChanged
requestDGV.Rows(0).Cells("requestTimeOff").Value = (DateTimePicker1.Value)
DateTimePicker1.Visible = False
DateTimePicker1.Enabled = False
End Sub
Super Basic , and i have it sitting directly in the box, doesn't look out of place
Super Basic ,我把它直接放在盒子里,看起来并不格格不入
Or super easy mode.......I just like to hide mine till column click
或者超级简单的模式.......我只是喜欢隐藏我的直到点击列
Public Sub DateTimePicker1_ValueChanged(sender As System.Object, e As System.EventArgs) Handles DateTimePicker1.ValueChanged
requestDGV.Rows(0).Cells("requestTimeOff").Value = (DateTimePicker1.Value)
End Sub
You really just need that one line.....data will be in the grid, just a lot less code.....
你真的只需要一行......数据将在网格中,只是少了很多代码......
回答by jhersey29
To solve some entry issues when using the DateTimePicker in a DataGridView you will want to add the following to the Microsoft Sample referenced above. It took quite a while to search out the problems with the valuechanged event not firing as expected. The fix came from here (stackoverflow) and translated to C# below. It seemed appropriate to add this information here as I keep finding this forum post when searching on DataGridView and DateTimePicker.
要解决在 DataGridView 中使用 DateTimePicker 时的一些输入问题,您需要将以下内容添加到上面引用的 Microsoft 示例中。花了很长时间才找出 valuechanged 事件未按预期触发的问题。修复来自这里 ( stackoverflow) 并转换为下面的 C#。在这里添加这些信息似乎很合适,因为我在 DataGridView 和 DateTimePicker 上搜索时不断找到这个论坛帖子。
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
switch (keyData & Keys.KeyCode)
{
case Keys.Enter:
case Keys.Tab:
this.dataGridView.Focus();
break;
}
return base.ProcessCmdKey(ref msg, keyData);
}
回答by Cilas
Ok... Using some of @rajat and @Aaron examples, i made one that pops up on the DateTimePicker cell. Thanks everyone.
好的...使用一些@rajat 和@Aaron 示例,我制作了一个在 DateTimePicker 单元格上弹出的示例。谢谢大家。
Private Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick
If e.ColumnIndex = 8 Then 'CHECK IF IT IS THE RIGHT COLUMN
'SET SIZE AND LOCATION
Dim rect = DataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True)
DateTimePicker1.Size = New Size(rect.Width, rect.Height)
DateTimePicker1.Location = New Point(rect.X + 10, rect.Y + 76) 'USE YOU OFFSET HERE
DateTimePicker1.Visible = True
ActiveControl = DateTimePicker1
End If
End Sub
Private Sub DateTimePicker1_ValueChanged(sender As Object, e As EventArgs) Handles DateTimePicker1.ValueChanged
If DataGridView1.RowCount > 0 Then 'JUST TO AVOID FORM LOAD CRASH
DataGridView1.CurrentCell.Value = DateTimePicker1.Value.ToShortDateString
DateTimePicker1.Visible = False
End If
回答by thomas
I think the CloseUp event on DateTimePicker is more appropriate because the changed value is triggering on any change while CloseUp only triggers when the entire date is selected
我认为 DateTimePicker 上的 CloseUp 事件更合适,因为更改的值会在任何更改时触发,而 CloseUp 仅在选择整个日期时触发

