DataGridViewComboBoxColumn:日期格式不适用于列表中的项目

时间:2019-06-06 10:47:45

标签: c# datagridview datagridviewcolumn

我目前正在使用DataGridView开发C#应用程序,并试图显示一个包含DateTime对象作为ValueType和ValueMember的DataGridViewComboBoxColumn。

我已经使用该列的DefaultCellStyle.Format方法应用了格式设置,但是这似乎仅适用于选定的值,而不适用于列表中的所有项目。

因此,当我选择某项内容时,它显示得很好,但是当打开下拉列表时,其中的所有项目都显示为DateTime对象的标准String表示形式。

这是预期的行为还是我错过了什么?

谢谢

Tobias Timpe

1 个答案:

答案 0 :(得分:0)

我猜想网格的数据源是DataTable,显然组合框列的类型是DateTime.。如果是这种情况,那么我相信您所描述的是因为网格单元“值”是实际的DateTime对象,并且网格将使用DateTime对象的默认ToString()方法(即…MM / DD / YYYY)来保持像元值。

您可以按照前面所述格式化显示,但是当下拉菜单可见时,该设置不适用于下拉菜单中的下拉菜单项。我猜上面可能是它以这种方式显示的原因。如果您尝试以其他方式设置格式,则很可能会出现网格令人恐惧的DataError

可能的解决方案...

由于组合框将包含DateTime个对象,并且您有一种获取DateTime对象的方法,因此我建议您将日期放入如下所示的DataTable中。这将是组合框的DataSource

private DataTable GetComboTable() {
  DataTable dt = new DataTable();
  dt.Columns.Add("DateTime", typeof(DateTime));
  dt.Columns.Add("StringDateTime", typeof(string));
  return dt;
}

第一列(DateTime)将包含“实际” DateTime对象,该对象将是组合框的ValueMember。这就是将映射到表格表中的DateTime列并避免使用DataError.

下一个(StringDateTime)列将包含要在下拉列表中显示的“格式化”日期字符串。该字符串将成为组合框DisplayMember.

下面是使用一些随机日期填充此表的示例。

private DataTable GetComboDates() {
  DataTable dt = GetComboTable();
  Random rand = new Random();
  int duration = 5 * 365;          
  DateTime randomDate = DateTime.Today.AddDays(-rand.Next(duration));
  for (int i = 0; i < 10; i++) {
    dt.Rows.Add(randomDate, String.Format("{0:yyyy/MM/dd - hh:mm:ss tt}", randomDate));
    randomDate = DateTime.Today.AddDays(-rand.Next(duration));
  }
  return dt;
}

请注意,此处格式化日期字符串适用于用户在显示下拉菜单时看到的内容。众所周知,如果组合列DefaultCellStyle.Format(适用于未选择组合框时用户看到的内容)与该格式不匹配,则它们将不同。这意味着列的显示格式必须与此处设置的格式匹配才能获得您描述的所需行为。

现在对于组合框列,我们有一个不错的DataSource,下面的函数将使用它返回用于网格的DataGridViewComboBoxColumn

private DataGridViewComboBoxColumn GetComboColumn() {
  DataGridViewComboBoxColumn comboCol = new DataGridViewComboBoxColumn();
  comboCol.DataPropertyName = "Dates";
  comboCol.HeaderText = "Dates";
  comboCol.DisplayMember = "StringDateTime";
  comboCol.ValueMember = "DateTime";
  comboCol.Width = 175;
  DataTable comboData = GetComboDates();
  comboCol.DataSource = comboData;
  return comboCol;
}

注意:DataPropertyName是网格DataTable中列的名称; DisplayMember是组合数据表中格式化日期字符串的列名; ValueMember是组合数据表中实际日期的列名。

下面是一个测试此示例的示例,我有信心在不显示下拉菜单时将保持下拉菜单的相同格式。只要两种格式都相同,就可以使用。

DataTable GridTable;

public Form1() {
  InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e) {
  GridTable = GetTable();
  FillTable(GridTable);
  dataGridView1.Columns.Add(GetComboColumn());
  dataGridView1.DataSource = GridTable;
}

private DataTable GetTable() {
  DataTable dt = new DataTable();
  dt.Columns.Add("Col0", typeof(string));
  dt.Columns.Add("Dates", typeof(DateTime));
  return dt;
}

private DataGridViewComboBoxColumn GetComboColumn() {
  DataGridViewComboBoxColumn comboCol = new DataGridViewComboBoxColumn();
  comboCol.DataPropertyName = "Dates";
  comboCol.HeaderText = "Dates";
  comboCol.DisplayMember = "StringDateTime";
  comboCol.ValueMember = "DateTime";
  comboCol.Width = 175;
  DataTable comboData = GetComboDates();
  comboCol.DataSource = comboData;
  return comboCol;
}

private void FillTable(DataTable dt) {
  for (int i = 0; i < 10; i++) {
    dt.Rows.Add("C0R" + i);
  }
}

private DataTable GetComboTable() {
  DataTable dt = new DataTable();
  dt.Columns.Add("DateTime", typeof(DateTime));
  dt.Columns.Add("StringDateTime", typeof(string));
  return dt;
}

private DataTable GetComboDates() {
  DataTable dt = GetComboTable();
  Random rand = new Random();
  int duration = 5 * 365;          
  DateTime randomDate = DateTime.Today.AddDays(-rand.Next(duration));
  for (int i = 0; i < 10; i++) {
    dt.Rows.Add(randomDate, String.Format("{0:yyyy/MM/dd - hh:mm:ss tt}", randomDate));
    randomDate = DateTime.Today.AddDays(-rand.Next(duration));
  }
  return dt;
}

希望这会有所帮助并且有意义。