【问题标题】:Populate datagridview combo box based on other dgv combobox selection根据其他 dgv 组合框选择填充 datagridview 组合框
【发布时间】:2021-08-09 12:47:59
【问题描述】:

我目前正在使用来自 db 查询的列表填充组合框,如下所示:

private List<ExerciseAndVideo> GetExerciseVideoComboBoxListFromDB()
    {
        List<ExerciseAndVideo> exerciseList = new List<ExerciseAndVideo>();

            con = new SqlConnection("my db path etc");
            cmd = new SqlCommand();
            con.Open();
            cmd.Connection = con;
            cmd.CommandText = "SELECT nome, link_video, gruppo_muscolare FROM Esercizi ORDER BY nome ASC";
            dr = cmd.ExecuteReader();

            while (dr.Read())
            {
                ExerciseAndVideo item = new ExerciseAndVideo();

                item.Esercizio = dr.GetString(0);
                item.Video = dr.GetString(1);
                item.Gruppo = dr.GetString(2);
                exerciseList.Add(item);
            }

            con.Close();

        return exerciseList;
    }

public class ExerciseAndVideo
        {
            public string Esercizio { get; set; }
            public string Video { get; set; }

            public string Gruppo { get; set; }
        }

        

我现在要做的是在 dgv 中添加另一个组合框,用于过滤锻炼列表的结果。

我添加了这样的组合:

    dataGridView1.Columns.Add(GetGroupComboBoxColumn(GrList));
private List<GroupList> GetGroupComboBoxListFromDB()
        {
            List<GroupList> GrList = new List<GroupList>();

            GrList.Add(new GroupList { Gruppo = "quads" });
            GrList.Add(new GroupList { Gruppo = "hamstring" });
            GrList.Add(new GroupList { Gruppo = "gluteus" });
           

            return GrList;
        }

我该怎么做?

我希望当在组合 1 中选择“四边形”时,在组合 2 中我只看到四边形的练习。

编辑

这里有在 dgv 组合上触发的事件:

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
        if (dataGridView1.Columns[dataGridView1.CurrentCell.ColumnIndex].Name == "Esercizio")
        {
            curCombo = e.Control as ComboBox;
            if (curCombo != null)
            {
                curCombo.SelectedIndexChanged -= new EventHandler(curCombo_SelectedIndexChanged);
                curCombo.SelectedIndexChanged += new EventHandler(curCombo_SelectedIndexChanged);
            }
        }
      
    }
    private void curCombo_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (curCombo != null && curCombo.SelectedValue != null)
        {
            ExerciseAndVideo selectedExercise = (ExerciseAndVideo)curCombo.SelectedItem;
            dataGridView1.CurrentRow.Cells["Video"].Value = selectedExercise.Video;
            dataGridView1.CurrentRow.Cells["Gruppo"].Value = selectedExercise.Gruppo;
        }
    }

   

    private void dataGridView1_CellLeave(object sender, DataGridViewCellEventArgs e)
    {
        if (dataGridView1.Columns[e.ColumnIndex].Name == "Esercizio")
        {
            if (curCombo != null)
            {
                curCombo.SelectedIndexChanged -= new EventHandler(curCombo_SelectedIndexChanged);
            }
        }
        

    }

这里组合如何获取数据源:

    private DataGridViewComboBoxColumn GetGroupComboBoxColumn(List<GroupList> GrList)
        {
            DataGridViewComboBoxColumn cbCol = new DataGridViewComboBoxColumn();
            cbCol.HeaderText = "Zona";
            cbCol.Name = "Zona";
            cbCol.DisplayMember = "Zona";
            cbCol.DataSource = GrList;
            cbCol.Width = 100;
            return cbCol;
        }
        
        
        private DataGridViewComboBoxColumn GetExcerciseComboBoxColumn(List<ExerciseAndVideo> exerciseList)
        {
            DataGridViewComboBoxColumn cbCol = new DataGridViewComboBoxColumn();
            cbCol.HeaderText = "Esercizio";
            cbCol.Name = "Esercizio";
            cbCol.DisplayMember = "Esercizio";


// if I use this string works fine
                   string selectedGroup = "quadricipiti";
                    var filteredList = exerciseList.Where(x => x.Gruppo == selectedGroup).ToList();


                 cbCol.DataSource = filteredList;

            cbCol.Width = 140;
            return cbCol;
        }

编辑 2

我按照建议编辑了 curCombo_SelectedIndexChanged 事件,但由于在函数中不存在,所以在 exerciseList 上出现错误:

private void curCombo_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (curCombo != null && curCombo.SelectedValue != null)
        {
            ExerciseAndVideo selectedExercise = (ExerciseAndVideo)curCombo.SelectedItem;
            dataGridView1.CurrentRow.Cells["Video"].Value = selectedExercise.Video;
            dataGridView1.CurrentRow.Cells["Gruppo"].Value = selectedExercise.Gruppo;

            string selectedGroup = Convert.ToString((GroupList)SelectedCombo.SelectedItem);
            DataGridViewComboBoxCell Esercizi = (DataGridViewComboBoxCell)(dataGridView1.CurrentRow.Cells["Esercizi"]);

          
             var filteredList = exerciseList.Where(x => x.Gruppo == selectedGroup).ToList();

             Esercizi.DataSource = filteredList;
        }
    }

编辑 3

更正列表代码以使其作为全局工作后,我没有收到任何错误,但我无法从组合 1 中选择选定的值作为选定组。

如果我使用“quads”之类的字符串或其他一切正常,否则如果我尝试从组合 1 中选择值,我会在组合 2 上得到一个空白列表。

这是我尝试从组合 1 中获取值的一些代码:

string selectedGroup = Convert.ToString(dataGridView1.CurrentRow.Cells["Zona"]);

string selectedGroup = SelectedCombo.SelectedItem.ToString();

string selectedGroup = Convert.ToString((GroupList)SelectedCombo.SelectedItem);

最后编辑

在这里我发现正在努力从组合 1 中获取价值:

string selectedGroup = Convert.ToString(dataGridView1.CurrentRow.Cells[0].FormattedValue.ToString());

现在的问题是,要使过滤器正常工作,我必须选择组合 1 中值的 2 倍。

例如,我在组合 1 中选择“quads”,在组合 2 中得到一个空白列表。我再次选择“quads”,得到过滤后的结果。

我认为问题可能出在事件中,但我没有看到错误:

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
        if (dataGridView1.Columns[dataGridView1.CurrentCell.ColumnIndex].Name == "Esercizio")
        {
            curCombo = e.Control as ComboBox;
            if (curCombo != null)
            {
                curCombo.SelectedIndexChanged -= new EventHandler(curCombo_SelectedIndexChanged);
                curCombo.SelectedIndexChanged += new EventHandler(curCombo_SelectedIndexChanged);
            }
        }
        if (dataGridView1.Columns[dataGridView1.CurrentCell.ColumnIndex].Name == "Zona")
        {
            curCombo = e.Control as ComboBox;
            if (curCombo != null)
            {
                curCombo.SelectedIndexChanged -= new EventHandler(ComboBox_SelectedIndexChanged);
                curCombo.SelectedIndexChanged += new EventHandler(ComboBox_SelectedIndexChanged);
            }
        }
    }
    private void curCombo_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (curCombo != null && curCombo.SelectedValue != null)
        {
            ExerciseAndVideo selectedExercise = (ExerciseAndVideo)curCombo.SelectedItem;
            dataGridView1.CurrentRow.Cells["Video"].Value = selectedExercise.Video;
            dataGridView1.CurrentRow.Cells["Gruppo"].Value = selectedExercise.Gruppo;

            
        }
    }

    private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (curCombo.SelectedValue != null)
        {

            string selectedGroup = Convert.ToString(dataGridView1.CurrentRow.Cells[0].FormattedValue.ToString());

            DataGridViewComboBoxCell Esercizi = (DataGridViewComboBoxCell)(dataGridView1.CurrentRow.Cells["Esercizio"]);

          //  string selectedGroup = "femorali";
            var filteredList = exerciseList.Where(x => x.Gruppo == selectedGroup).ToList();

            Esercizi.DataSource = filteredList;

        }
    }

    private void dataGridView1_CellLeave(object sender, DataGridViewCellEventArgs e)
    {
        if (dataGridView1.Columns[e.ColumnIndex].Name == "Esercizio")
        {
            if (curCombo != null)
            {
                curCombo.SelectedIndexChanged -= new EventHandler(curCombo_SelectedIndexChanged);
            }
        }
        if (dataGridView1.Columns[e.ColumnIndex].Name == "Zona")
        {
            if (curCombo != null)
            {
                curCombo.SelectedIndexChanged -= new EventHandler(ComboBox_SelectedIndexChanged);
            }
        }

    }

【问题讨论】:

  • 我可以推测的是……网格中有两列组合框。在组合框第 1 列中,每个组合框都包含锻炼视频项目?在组合框第 2 列中,每个组合框都包含“四边形”等项......如图所示。您想要的是,当用户从第 2 列的组合框中选择一个值时,该组合框 1 将被过滤为仅包含与“四边形”或用户选择的任何内容相关的视频。这个对吗?如果是这样,下面的链接可能会有所帮助。
  • 嗨,JohnG,是的,这就是我想要做的。您的回答非常完整,但让我感到困惑。我将尝试在新的 win 表单上实现它,然后在我的代码中实现它
  • @JohnG 经过几次尝试,我无法让它为我工作。我试图用我的数据更改银行和分行,但由于代码是为另一种逻辑设计的,所以我在某处丢失了
  • 我同意银行分行有点不同。我把银行想象成一个“集团”对象,把分行想象成一个ExcerciseAndVdeo 对象。在银行分行示例中,一个区别是银行(集团)保留了有关哪些分行(练习视频)属于该银行(集团)的信息。在您的示例中,它有点相反,因为每个组保留属于该组的所有锻炼视频的列表是没有意义的。视频保留 IT 所属组的列表更有意义。

标签: c# datagridview


【解决方案1】:

来自 cmets 的长来回。我在下面有一个解决方案,应该可以按照您的描述工作。在我开始之前,我想建议您在发布问题时要多加小心。最初,当您发布此问题时,遗漏了许多细节,这些细节可以避免您看到的不必要的扩展 cmets。您遗漏的细节越多,其他人为理解您的问题而提出的问题越多,您得到回答的机会就越小。

以后,我建议您提供所有需要的信息,并且如果很明显需要,请务必编辑您的问题以添加任何相关信息。别人为帮助你所做的工作越多,你得到任何帮助的机会就越少,更不用说得到答案了。帮自己一个忙,并采取额外的步骤,以确保您的问题完全可以理解,并且可以更好地重现……我保证您不会后悔。

继续,鉴于下面的图片,我假设这与您发布的内容相似。

用户可以选择和更改“区域”组合框项目。发生这种情况时,我们要做的是“过滤”“练习”列组合框单元格以仅包含所选区域中的练习。那么,如果用户从练习组合框单元格中选择一个练习,那么,该练习的匹配“视频”链接将显示在该行的“视频”单元格中。希望这是正确的。

观察会导致一些其他假设行为。

  1. 如果一行有一个选定的区域和一个选定的练习,并且视频单元格显示练习的视频链接……那么……如果用户更改该行的“区域”值,那么代码将清除练习和视频单元格,因为这些值不一定属于新选择的区域。

  2. 假设区域组合框单元格为“空”...如果用户在为该行设置区域值之前尝试从练习组合框中选择一个练习...那么...我们希望练习组合框包含 NO 值因为尚未选择区域。换句话说,在用户选择区域之前,练习组合框不会填充值。

以下代码使用上述假设,并在区域更改时清除锻炼和视频值,并阻止用户在选择区域之前选择锻炼。

如果您创建一个新的 winform 解决方案并将 DataGridView 拖放到表单上,您应该能够按照步骤逐步完成此示例。下面是一些有助于测试数据和构建网格的代码和类。

首先是我们将用于组合框列的两个类。两者都很简单且相当直接。

public class ExerciseAndVideo {
  public string Exercise { get; set; }
  public string Video { get; set; }
  public string ZoneName { get; set; }
}

public class Zone {
  public string ZoneName { get; set; }
}

使用组合框的一些测试数据填充全局变量 ExerciseListZoneList 的一些额外代码...

private void SetExerciseListFromDB() {
  ExerciseList = new List<ExerciseAndVideo>();
  ExerciseList.Add(new ExerciseAndVideo { Exercise = "-", ZoneName = "-", Video = "" });
  ExerciseList.Add(new ExerciseAndVideo { Exercise = "Exercise 1", ZoneName = "quads", Video = "Video 1" });
  ExerciseList.Add(new ExerciseAndVideo { Exercise = "Exercise 2", ZoneName = "gluteus", Video = "Video 2" });
  ExerciseList.Add(new ExerciseAndVideo { Exercise = "Exercise 3", ZoneName = "quads", Video = "Video 3" });
  ExerciseList.Add(new ExerciseAndVideo { Exercise = "Exercise 4", ZoneName = "hamstring", Video = "Video 4" });
  ExerciseList.Add(new ExerciseAndVideo { Exercise = "Exercise 5", ZoneName = "quads", Video = "Video 5" });
  ExerciseList.Add(new ExerciseAndVideo { Exercise = "Exercise 6", ZoneName = "hamstring", Video = "Video 6" });
  ExerciseList.Add(new ExerciseAndVideo { Exercise = "Exercise 7", ZoneName = "quads", Video = "Video 7" });
  ExerciseList.Add(new ExerciseAndVideo { Exercise = "Exercise 8", ZoneName = "gluteus", Video = "Video 8" });
}

private void SetZoneListFromDB() {
  ZoneList = new List<Zone>();
  ZoneList.Add(new Zone { ZoneName = "-" });
  ZoneList.Add(new Zone { ZoneName = "quads" });
  ZoneList.Add(new Zone { ZoneName = "hamstring" });
  ZoneList.Add(new Zone { ZoneName = "gluteus" });
}

注意:在上面的代码中,您可能会注意到每个练习和区域列表都添加了一个附加项,用于表示用户没有选择......

ExerciseList.Add(new ExerciseAndVideo { Exercise = "-", ZoneName = "-", Video = "" });

ZoneList.Add(new Zone { ZoneName = "-" });

我们可以不用这些“空白”(没有选择)值; however, we will need a way to set the Exercise combo box to some “blank” value when a different Zone is selected.您可以像列表中的第一个练习一样设置默认值,这将起作用。这里的要点是,如果我们不将练习值设置为属于“过滤”练习的“过滤”版本的值......您将收到网格的 DataError 抱怨单元格中的值不是项目组合框列表中的有效值。

这适用于用户“更改”区域组合框值并且练习单元格已包含先前设置的区域值中的值的情况。如果我们不将练习值更改为新过滤版本中的“某物”,而只是将练习值保留为旧值……那么我们将获得网格的DataError

这是在练习列表中添加“空白”无选择值背后的逻辑。当我们过滤列表时,我们会将这个“空白”值添加到列表中,然后在区域更改时将练习值设置为那个“空白”值。这样,我们几乎可以保证我们将避免网格的DataError,因为练习单元格中的值无效。还有其他方法可以解决这个问题,但是,我发现这个“空白”非选择值在处理相互关联的组合框时会变得更容易。我希望这是有道理的。

接下来是手动设置网格列的代码,包括区域和练习组合框列。您可能需要考虑在最后给网格一个DataSource... 更多信息。

private void AddColumnsToGrid() {
  DataGridViewComboBoxColumn cbCol = GetComboBoxColumn("Zone", "Zone", "ZoneName", 100);
  cbCol.DataSource = ZoneList;
  dataGridView1.Columns.Add(cbCol);
  cbCol = GetComboBoxColumn("Exercise", "Exercise", "Exercise", 140);
  cbCol.DataSource = ExerciseList;
  dataGridView1.Columns.Add(cbCol);
  dataGridView1.Columns.Add(GetTextBoxColumn("Serie", "serie"));
  dataGridView1.Columns.Add(GetTextBoxColumn("Ripetizioni", "ripetizioni"));
  dataGridView1.Columns.Add(GetTextBoxColumn("Recupero", "recupero"));
  dataGridView1.Columns.Add(GetTextBoxColumn("Time under tension", "tut"));
  dataGridView1.Columns.Add(GetLinkColumn("Video", "Video"));
  dataGridView1.Columns.Add(GetTextBoxColumn("Note", "note"));
}

private DataGridViewComboBoxColumn GetComboBoxColumn(string headertext, string name, string displayMember, int width) {
  DataGridViewComboBoxColumn cbCol = new DataGridViewComboBoxColumn();
  cbCol.HeaderText = headertext;
  cbCol.Name = name;
  cbCol.DisplayMember = displayMember;
  cbCol.Width = width;
  return cbCol;
}

private DataGridViewTextBoxColumn GetTextBoxColumn(string headerText, string name) {
  DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
  col.HeaderText = headerText;
  col.Name = name;
  return col;
}

private DataGridViewLinkColumn GetLinkColumn(string headerText, string name) {
  DataGridViewLinkColumn col = new DataGridViewLinkColumn();
  col.HeaderText = headerText;
  col.Name = name;
  return col;
}

如果我们现在运行代码,它将如上图所示。用户可以选择任何区域和任何练习。练习组合框的过滤尚未实现,视频单元格的设置也未实现。因此,无论选择哪个区域,您都应该在组合框中看到所有区域和所有练习。

接下来,当用户更改区域组合框的值时,我们将对练习组合框应用“过滤”。总体方法是这样的……首先,我们要创建一个全局常规变量ComboBox,我们将其称为CurCombo。然后我们将连接网格的EditingControlShowing 事件。当用户单击网格单元格并开始编辑该单元格时会触发此事件。请记住……此事件在用户实际对单元格进行任何更改之前触发。在这种情况下,我们将查看编辑的单元格是否是区域单元格。如果编辑的单元格是区域单元格,那么……我们要做的就是将网格的组合框单元格转换为我们的全局 CurCombo 变量。这看起来像……

CurCombo = e.Control as ComboBox;

其中e 是传入的DataGridViewEditingControlShowingEventArgs 变量。它将允许我们将单元格转换为常规组合框。然后,我们将连接CurComboSelectedIndexChanged 事件然后退出并等待用户更改组合框的索引。

当用户确实更改了 Zone 组合框索引,并且组合框 SelectedIndexChanged 事件触发......那么我们将知道我们需要根据所选区域“过滤”Exercise 组合框。

更复杂的事情......如果用户更改了练习组合框之一,那么我们想要更新视频单元格以显示指向所选视频的链接。我们可以创建另一个ComboBox 并执行与区域组合框相同的操作,但是,我们知道用户不能同时选择两个组合框。所以我们可以对两个组合框使用相同的CurCombo 变量。但是……我们需要确保在用户离开单元格时取消连接CurComboSelectedIndexChanged 事件。否则,当任一组合框更改时,两个事件都将开始触发。

考虑到两个组合框都会触发网格的EditingControlShowingEvent 事件,如果组合框是练习组合框,我们需要采取额外的步骤。在我们连接CurComboSelectedIndexChanged 事件之前,我们要检查区域组合框是否有值。如果区域组合框没有值,那么我们不希望练习组合框包含除空白无选择值之外的任何值。我们希望用户首先选择一个区域。

因此,如果练习组合框被编辑并且区域组合框单元格不为空,那么我们只需连接CurComboSelectedIndexChanged 事件以指向将更新视频单元格的不同事件方法,然后退出并等待用户更改练习值。如果区域单元格为空,那么我们将过滤练习组合框以仅包含我们的 BLANK Non-choice 值,并且我们不会连接 CurCombo 事件,因为用户无论如何都无法选择练习。

看起来有很多代码;但是,我在代码中添加了一些调试语句,以便我们可以在“输出”窗口中看到输入事件的时间和退出时间,并显示连接了哪个事件。这可能有助于调试,一旦你完全工作,我会删除调试语句。

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) {
  Debug.WriteLine("DGV_EditingControlShowing <- Enter");
  if (dataGridView1.Columns[dataGridView1.CurrentCell.ColumnIndex].Name == "Exercise") {
    if (dataGridView1.CurrentRow.Cells["Zone"].Value != null &&  // <- Zone is not null
        !string.IsNullOrEmpty(dataGridView1.CurrentRow.Cells["Zone"].Value.ToString()) &&  // <- Zone is not an empty string
        dataGridView1.CurrentRow.Cells["Zone"].Value.ToString() != "-") {  // <= Zone is not "-" blank value
      CurCombo = e.Control as ComboBox;
      if (CurCombo != null) {
        Debug.WriteLine("----------Wiring up Exercise combo box");
        CurCombo.SelectedIndexChanged -= new EventHandler(ExerciseComboBox_SelectedIndexChanged);
        CurCombo.SelectedIndexChanged += new EventHandler(ExerciseComboBox_SelectedIndexChanged);
      }
    }
    else {
      // NO Zone is selected - set the Exercise combo box item list to our single blank value
      DataGridViewComboBoxCell ExerciseCell = (DataGridViewComboBoxCell)(dataGridView1.CurrentRow.Cells["Exercise"]);
      var filteredList = ExerciseList.Where(x => x.ZoneName == "-").ToList();
      Debug.WriteLine("----------Zone is empty filtering Exercise combo box to single blank value");
      ExerciseCell.DataSource = filteredList;
    }
  }
  else {
    if (dataGridView1.Columns[dataGridView1.CurrentCell.ColumnIndex].Name == "Zone") {
      CurCombo = e.Control as ComboBox;
      if (CurCombo != null) {
        Debug.WriteLine("----------Wiring up Zone combo box");
        CurCombo.SelectedIndexChanged -= new EventHandler(ZoneComboBox_SelectedIndexChanged);
        CurCombo.SelectedIndexChanged += new EventHandler(ZoneComboBox_SelectedIndexChanged);
      }
    }
  }
  Debug.WriteLine("DGV_EditingControlShowing -> Leave");
}

接下来我们需要实现ExerciseComboBox_SelectedIndexChangedZoneComboBox_SelectedIndexChanged 事件方法……再次添加调试语句以帮助调试。需要注意的是,如果我们将List&lt;ExerciseAndVideo&gt; 用作组合框列的DataSource,那么不要尝试直接从网格单元格中获取组合框值……我建议您直接获取ExerciseAndVideo 对象来自组合框 SelectedItem 属性。我们应该可以像…

ExerciseAndVideo EandV = (ExerciseAndVideo)CurCombo.SelectedItem;

Zone selectedZone = (Zone)CurCombo.SelectedItem;

这应该更容易在网格单元格中获取新选择的值。

private void ExerciseComboBox_SelectedIndexChanged(object sender, EventArgs e) {
  Debug.WriteLine("ExerciseComboBox_SelectedIndexChanged <- Enter");
  if (CurCombo != null) {
    ExerciseAndVideo EandV = (ExerciseAndVideo)CurCombo.SelectedItem;
    dataGridView1.CurrentRow.Cells["Video"].Value = EandV.Video;
  }
  Debug.WriteLine("ExerciseComboBox_SelectedIndexChanged -> Leave");
}

private void ZoneComboBox_SelectedIndexChanged(object sender, EventArgs e) {
  Debug.WriteLine("ZoneComboBox_SelectedIndexChanged <- Enter");
  if (CurCombo.SelectedValue != null) {
    Zone selectedZone = (Zone)CurCombo.SelectedItem;
    DataGridViewComboBoxCell ExerciseCell = (DataGridViewComboBoxCell)(dataGridView1.CurrentRow.Cells["Exercise"]);
    var filteredList = ExerciseList.Where(x => x.ZoneName == selectedZone.ZoneName || x.ZoneName == "-").ToList();
    Debug.WriteLine("----------Exercises combo filtered");
    ExerciseCell.DataSource = filteredList;
    dataGridView1.CurrentRow.Cells["Exercise"].Value = "-";
    dataGridView1.CurrentRow.Cells["Video"].Value = "";
  }
  Debug.WriteLine("ZoneComboBox_SelectedIndexChanged -> Leave");
}

几乎完成...如果我们现在运行代码,您将能够更改区域组合框,但是,如果我们更改区域组合框的值,然后单击其中一个练习组合框,您将在ZoneComboBox_SelectedIndexChanged 方法。错误的原因是当我们单击区域组合框时,全局CurComboSelectedIndexChanged 被连接起来指向过滤练习组合框的方法。 Therefore, when the Exercise combo is selected, the code will fail and throw a casting exception when it tries to cast the combo box to an Zone object and it is really an ExerciseAndVideo object.

这与前面的评论有关,我们必须确保在用户离开单元格时取消连接CurComboSelectedIndexChanged 事件。此示例中使用的方法是简单地连接网格的CellLeave 事件,在这种情况下,我们将检查哪个单元格正在结束其编辑(Zone 或ExerciseAndVideo),然后取消连接CurCombo 的@ 987654376@ 事件。网格的CellLeave 事件可能类似于。

private void dataGridView1_CellLeave(object sender, DataGridViewCellEventArgs e) {
  Debug.WriteLine("DGV_CellLeave <- Enter");
  if (CurCombo != null) {
    string colName = dataGridView1.Columns[e.ColumnIndex].Name;
    switch (colName) {
      case "Exercise":
        Debug.WriteLine("----------UN-Wiring Exercise combo box");
        CurCombo.SelectedIndexChanged -= new EventHandler(ExerciseComboBox_SelectedIndexChanged);
        break;
      case "Zone":
        Debug.WriteLine("----------UN-Wiring Zone combo box");
        CurCombo.SelectedIndexChanged -= new EventHandler(ZoneComboBox_SelectedIndexChanged);
        break;
      default:
        break;
    }
  }
  Debug.WriteLine("DGV_CellLeave -> Leave");
}

最后,网格的DataError 事件被连接起来以帮助调试。

private void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e) {
  MessageBox.Show("Error: From row: " + e.RowIndex + "Col: " + e.ColumnIndex + " Message: " + e.Exception.Message);
}

将所有这些放在Load 事件的形式中可能如下所示。那应该这样做。下面展示了这一点。

using System.Diagnostics;
using System.Linq;

List<ExerciseAndVideo> ExerciseList;
List<Zone> ZoneList;
ComboBox CurCombo;

public Form1() {
  InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e) {
  SetZoneListFromDB();
  SetExerciseListFromDB();
  AddColumnsToGrid();
  dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;
}

最后,如前所述,此示例使用未绑定到数据源的网格。如果您打算为包含现有数据的网格使用数据源……那么添加两个额外步骤是明智的。

  1. 在设置网格的数据源之前...强烈建议您检查数据源中的每个区域和行使值。如果有一个区域或练习不是区域或练习列表,则网格将在设置网格的数据源时抛出其DataError。此外,如果一个练习不属于给定区域,则网格将抛出其DataError。换句话说,如果对一行数据的练习不属于它所拥有的区域,那么您需要在设置网格的DataSource 之前解决这个问题。

  2. 一旦您检查以确保区域和练习数据是正确的,那么在设置网格的数据源之后,您将需要遍历网格中的所有行并根据所选的“过滤”每个练习组合框区。当数据加载到网格中时,显然我们之前使用的事件不会被触发。幸运的是,您只需在加载数据后执行一次。

我希望这有意义并有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-03
    • 1970-01-01
    相关资源
    最近更新 更多