【问题标题】:Can a bound DataGridView set display value of a DGVComboCell bound to another source绑定的 DataGridView 可以设置绑定到另一个源的 DGVComboCell 的显示值吗
【发布时间】:2019-05-02 00:55:52
【问题描述】:

我有一个绑定到列表的 DGV。

Work 是一个包含许多属性的类,其中包括一个 int 类型的状态属性。我希望在 DataGridViewComboBoxCell 中有该状态值,该值映射到适当的显示值。

所以映射看起来像

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

我尝试将 DataGridViewComboBoxCell 绑定到一个包含状态的 int 和 string 值的 List。

我一直无法弄清楚如何让 work.status 在 DataGridViewComboBoxCell 中显示 Statuses.DisplayName。

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;}

}

如果可以的话,请告诉我..

【问题讨论】:

  • 在不改变当前结构的情况下,您可以添加一个新的DataGridViewComboBoxColumn,将其DataSource 设置为List<Statuses> (DisplayMemeber = "DisplayValue", Valuemember = "id"),设置其DisplayIndex = 3并隐藏与status 属性对应的列。在CellFormatting事件中,将ComboBox列的.Value设置为status属性的.Value,在CellEndEdit中,e.ColumnIndex == [Your ComboBox column]时,反之。请注意,无需进一步调整,status 属性的值只会在当前单元格发生变化时更新。
  • 好吧,如果描述不是很容易理解并且您需要一个示例,请告诉我:)
  • 就像 Jimmy 所说的,但是 DataGridViewComboBoxColumn 有一个名为 DataPropertyName 的属性,将其设置为“status”应该会更轻松。
  • @M.Ruiz 我认真地尝试过,但在尝试时收到错误消息。所以我显然在代码中有问题。又试了一次,第一次弹出。
  • @Jimi 我正要开始沿着你建议的道路前进,然后在另一个有效的评论中重试了该建议。谢谢

标签: c# winforms datagridview datagridviewcomboboxcell


【解决方案1】:

cmets 中建议的一种可能解决方案是按照您描述的方式“创建”DataGridViewComboBoxColumn,然后将其添加到网格中。在设置网格数据源之前执行此操作。将此组合框列映射到Work 列表的“WorkStatus”属性是使用组合列DataPropertyName 完成的。将列 DataPropertyName 设置为“WorkStatus”应该可以解决问题。

您可能会遇到的一个重要问题是,如果在设置组合框列后使用 1 – Complete, 2 – In Progress... 等。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 方法。这将有助于使用列表的 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),然后循环通过 @ 987654340@ 项添加任何尚未在状态列表中的值。

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 对象WorkStatus 属性。如果这不匹配,则该列将无法正确映射。添加的“状态”列最终将作为网格中的第一列,因此您可能需要更改其序数值。

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);
}

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    • 2013-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多