首页 > 解决方案 > DataGridViewComboBoxColumn:日期格式不适用于列表中的项目

问题描述

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

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

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

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

谢谢,

托拜厄斯·廷佩

标签: c#datagridviewdatagridviewcolumn

解决方案


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

正如您所说,您可以格式化显示,但是当下拉可见时,这不适用于组合框中的下拉项。我猜上面可能是它以这种方式显示的原因。如果您尝试以任何其他方式对其进行格式化……网格的 dreadedDataError很可能会出现。

一个可能的解决方案……</p>

由于组合框将包含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;
}

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


推荐阅读