Может ли связанный DataGridView установить отображаемое значение DGVComboCell, связанного с другим источником - PullRequest
0 голосов
/ 02 мая 2019

У меня есть DGV, связанный с List.

Work - это класс, который содержит ряд свойств, включающих свойство status типа int.Я хотел бы иметь это значение Status в DataGridViewComboBoxCell, которое отображается на соответствующее значение отображения.

Таким образом, отображение будет выглядеть как

1 = Completed   
2 = In Progress   
3 = Errored   
4 = On Hold

Я попытался связать DataGridViewComboBoxCell со спискомкоторый содержит int и строковые значения статусов.

Мне не удалось выяснить, как заставить work.status отображать Statuses.DisplayName в DataGridViewComboBoxCell.

public class Work
{
    public int id {get; set;}
    public string name {get; set;}
    public int status {get; set;}
    public datetime created {get; set;}
    public datetime modified {get; set;}
}

public class Statuses
{
    public int id {get; set;}
    public string DisplayValue {get; set;}

}

Если это можно сделать, пожалуйста, дайте мне знать ..

1 Ответ

0 голосов
/ 03 мая 2019

Одним из возможных решений, как предлагается в комментариях, является «создание» 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);
}

Надеюсь, это поможет.

...