在.NET2.0 环境中,使用DataGridView控件时,经常会遇到需要处理可空的 DateTime 列的情况。无论是 Oracle PL/SQL 还是MS SQL Server,当数据库中的 DateTime 列允许 NULL 值时,标准的 DataGridView 并不能很好地处理这种情况。本文将介绍一种解决方案,以确保 DataGridView 能够正确地显示和编辑这些可空的 DateTime 列。
在 Oracle PL/SQL 中,如果定义了一个允许 NULL 值的 DATE 类型的列,例如:
CREATE TABLE example (
dtReceived DATE
);
或者在MS SQL Server中,定义了一个允许 NULL 值的 DATETIME 类型的列,例如:
CREATE TABLE example (
dtReceived DATETIME NULL
);
在这种情况下,标准的 DataGridView 控件在显示和编辑这些列时会遇到问题。虽然可以通过 Google 搜索找到 Microsoft 的示例,但这些示例通常不足以解决实际问题。
经过大量的网络搜索,发现了一篇关于可空 DateTimePicker 的文章。在此基础上,进行了一些修改,使其能够适用于 DataGridView 控件。
为了避免命名冲突,将 DateTimePicker 类重命名为 DatePicker。
public class DatePicker : System.Windows.Forms.DateTimePicker
{
// ...
}
在 DatePicker 类中添加以下代码片段:
public string ToShortDateString()
{
if (!this.realDate)
return String.Empty;
else
{
DateTime dt = (DateTime)this.Value;
return dt.ToShortDateString();
}
}
根据 Microsoft 示例,修改 CalendarEditingControl 类以适应 DatePicker:
class CalendarEditingControl : DatePicker, IDataGridViewEditingControl
{
// ...
}
根据 Microsoft 示例,修改 CalendarCell 类以处理 DBNull:
public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
{
base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
CalendarEditingControl ctl = dataGridView.EditingControl as CalendarEditingControl;
object val = null;
try
{
val = this.Value;
}
catch (Exception ex)
{
// Argument out of range (value doesn't exist in collection)
return;
}
if (val != System.DBNull.Value)
ctl.Value = (DateTime)val;
}
以下是如何在项目中使用 DatePicker 类的示例代码:
private void Form1_Load(object sender, EventArgs e)
{
CalendarColumn col = new CalendarColumn();
this.dataGridView1.Columns.Add(col);
this.dataGridView1.RowCount = 5;
foreach (DataGridViewRow row in this.dataGridView1.Rows)
{
row.Cells[0].Value = DateTime.Now;
}
}