Одним из возможных решений, как предлагается в комментариях, является «создание» DataGridViewComboBoxColumn
, как вы описываете, а затем добавление его в сетку. Сделайте это, прежде чем установить источник данных сетки. Сопоставление этого столбца поля со списком со свойством «WorkStatus» списка Work
выполняется с помощью столбцов со списком DataPropertyName
. Установка столбцов DataPropertyName
в «WorkStatus» должна помочь.
Одна важная проблема, с которой вы можете столкнуться, если ПОСЛЕ установки столбца со списком со значениями 1 - Завершено, 2 - В процессе ... и т. Д. Значения int
1-4 являются значениями в поле «Состояние» список Work
предметов… НАДЕЖДА! Это всегда может иметь место, однако, если значение одного из полей Status
НЕ равно 1, 2, 3 или 4 ... тогда сетка будет выбрасывать DataError
, когда это значение отображается в столбце комбинированного окна , В большинстве случаев вы не узнаете об этом, пока данные не будут прочитаны и не произойдет сбой бума.
Дело в том, что если вы собираетесь настроить столбец со списком, а затем «сопоставить» столбец из источника данных с этим столбцом ... лучше быть чертовски уверенным, что у него нет недопустимых значений «статуса». В противном случае сбой (ошибка данных) гарантирован. В любом случае было бы разумно подключить DataError
.
Учитывая это, необходимо как минимум «проверить», чтобы убедиться, что что-то подобное не происходит, когда данные привязаны к сетке. Одно простое решение состоит в том, чтобы перебрать все данные (перед их привязкой к сетке) и «проверить значения« статуса »каждого элемента Work
. Неизвестно, что делать, если в данных найдено значение больше 4 или меньше 1. Вы не можете просто отпустить, как описано выше. Это решение состоит в том, чтобы просто «добавить» значение в поле со списком «неизвестное» строковое значение. Это как минимум «гарантирует», что вы избежите ошибки данных из-за недопустимых значений.
Соединение этого может пойти примерно так ...
Ниже приведен класс Work, опубликованный, однако я изменил некоторые имена переменных. Это класс, который связан с сеткой.
public class Work {
public int WorkID { get; set; }
public string WorkName { get; set; }
public int WorkStatus { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
}
Далее, это класс Status
, который используется для определения объектов Status
. Это используется для столбца со списком. Конструктор добавляется вместе с переопределенными Equals
методами. Это облегчит «проверку», чтобы увидеть, есть ли уже существующее значение «Status» в списке, используя свойство списка Contains
.
public class Status : IEquatable<Status> {
public int StatusID { get; set; }
public string StatusString { get; set; }
public Status(int statusID, string statusString) {
StatusID = statusID;
StatusString = statusString;
}
public override bool Equals(object obj) {
if (obj.GetType() != GetType()) return false;
return Equals(obj as Status);
}
public bool Equals(Status that) {
return that != null && this.StatusID == that.StatusID;
}
public override int GetHashCode() {
var hashCode = -1280899892;
hashCode = hashCode * -1521134295 + StatusID.GetHashCode();
return hashCode;
}
}
Настройка ListOfStatus
потребует циклического перебора списка объектов Work
и «проверки» каждого из значений состояния, убедившись, что значения находятся в диапазоне от 1 до 4 включительно. Метод, который возвращает этот список, может пригодиться и выглядеть примерно так: сначала создаются значения «по умолчанию» Status
и добавляются в список (1, 2, 3, 4), затем цикл по Work
пунктов для добавления любых значений, которых еще нет в списке состояний.
private List<Status> GetStatusList(List<Work> workItems) {
List<Status> listOfStatus = new List<Status>();
// add the default values for the combo boxes
Status curStatus = new Status(1, "Complete");
listOfStatus.Add(curStatus);
curStatus = new Status(2, "In Progress");
listOfStatus.Add(curStatus);
curStatus = new Status(3, "Errored");
listOfStatus.Add(curStatus);
curStatus = new Status(4, "On Hold");
listOfStatus.Add(curStatus);
// check to make sure the data (workItems) does NOT have any values in the Status field...
// that are NOT one of the values above... (specifically 1, 2, 3 or 4)
// if the value is NOT one of the values above... we will simply add it to the list
Status unknownStatus;
foreach (Work work in workItems) {
if (work.WorkStatus < 1 || work.WorkStatus > 4) {
unknownStatus = new Status(work.WorkStatus, "Unknown_" + work.WorkStatus);
if (!listOfStatus.Contains(unknownStatus)) {
listOfStatus.Add(unknownStatus);
}
}
}
return listOfStatus;
}
Теперь, когда у нас есть хороший список Status
объектов, мы можем приступить к созданию столбца со списком и использовать этот список в качестве источника данных для столбца со списком. Учитывая список Work
объектов, это все, что нам нужно для создания этого столбца, и метод, который возвращает этот DataGridViewComboBoxColumn
, может выглядеть примерно так: Сначала мы получаем список состояний из вышеприведенного метода, а затем устанавливаем свойства столбцов, следя за тем, чтобы столбцы DataPropertyName
соответствовали свойству Work
objects WorkStatus
. Если это не совпадает, столбец не будет отображаться должным образом. Добавленный столбец «status» будет отображаться как первый столбец в сетке, поэтому вы можете изменить его порядковое значение.
private DataGridViewComboBoxColumn GetComboColumn(List<Work> listOfWork) {
List<Status> ListOfStatus = GetStatusList(listOfWork);
DataGridViewComboBoxColumn comboCol = new DataGridViewComboBoxColumn();
comboCol.Name = "Status";
comboCol.DataPropertyName = "WorkStatus";
comboCol.DisplayMember = "StatusString";
comboCol.ValueMember = "StatusID";
comboCol.DataSource = ListOfStatus;
return comboCol;
}
Пример использования вышеуказанных методов приведен ниже.
private void Form1_Load(object sender, EventArgs e) {
List<Work> ListOfWork = new List<Work>();
FillListOfWork(ListOfWork);
dataGridView1.Columns.Add(GetComboColumn(ListOfWork));
dataGridView1.DataSource = ListOfWork;
}
private void FillListOfWork(List<Work> ListOfWork) {
Work newWork;
Random rand = new Random();
for (int i = 0; i < 100; i++) {
newWork = new Work();
newWork.WorkID = i;
newWork.WorkName = "Work Name " + i;
newWork.WorkStatus = rand.Next(1, 5);
newWork.DateCreated = DateTime.Now;
newWork.DateModified = DateTime.Now;
ListOfWork.Add(newWork);
}
}
private void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e) {
MessageBox.Show("DataError: " + e.Exception.Message);
}
Надеюсь, это поможет.