DataGridViewComboBoxColumn: формат даты не применяется к элементам в списке - PullRequest
0 голосов
/ 06 июня 2019

В настоящее время я разрабатываю приложение C # с DataGridView и пытаюсь показать DataGridViewComboBoxColumn, содержащий объекты DateTime, в качестве ValueType и ValueMember.

Я уже применил форматирование с использованием метода столбца DefaultCellStyle.Format, однакокажется, что это применимо только к выбранному значению, а не ко всем элементам в списке.

Так что, когда у меня есть что-то выделенное, оно отображается нормально, но при открытии выпадающего списка все элементы в нем отображаются какстандартное строковое представление объекта DateTime.

Это предполагаемое поведение или я что-то упустил?

Спасибо,

Тобиас Тимпе

1 Ответ

0 голосов
/ 08 июня 2019

Я предполагаю, что источником данных сетки является 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;
}

Надеюсь, что это помогает и имеет смысл.

...