当前位置: 首页 > 知识库问答 >
问题:

基于选定的ComboBox项填充datagridview

樊腾
2023-03-14

我有一个数据网格,其中组合框是从Db填充的。

我试图实现的是,当我在“Esercizio”列中选择一些内容时,“Video”列的单元格会自动填充Db的“link_video”列中的相应值。

因此,如果我选择“回扣”,我需要在文本框单元格中看到来自db的回扣链接视频。

这是我用来在表单加载时填充组合框的代码:

private void Myform_Load(对象发送方,EventArgs e) {

        con = new SqlConnection("Data Source=(LocalDB)\\etc");
        cmd = new SqlCommand();
        con.Open();
        cmd.Connection = con;
        cmd.CommandText = "SELECT * FROM Esercizi";
        dr = cmd.ExecuteReader();

        while (dr.Read())
        {
          //populate Column1 combobox with "nome" column from Esercizi db table
            Column1.Items.Add(dr["nome"]);
            
        }

        con.Close();
    }

数据网格视图

编辑我已经解决了两个新问题。

我正在尝试从数据库加载保存的锻炼,但是当我这样做时,没有视频链接填充 dgv,因为网格事件不会触发。

我尝试的是将foreach循环添加到一个新的selectionindexchanged函数中,并在Load Button代码的末尾触发它,如下所示:

private void curCombo_LoadedValues(object sender, EventArgs e)
        {

            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                foreach (DataGridViewCell cell in row.Cells)
                {
                    if (curCombo != null && curCombo.SelectedValue != null)
                    {
                        ExerciseAndVideo selectedExercise = (ExerciseAndVideo)curCombo.SelectedItem;
                        dataGridView1.CurrentRow.Cells["Video"].Value = selectedExercise.Video;

                    }
                }
            }
        }

私有void按钮9_Click(对象发送方,EventArgs e){

    string connectionString = "Data Source=(LocalDB)\\etc";
    string sql = "SELECT * FROM Schede WHERE Id = 6 AND dgv = 'dataGridView1'";
    SqlConnection connection = new SqlConnection(connectionString);
    SqlDataAdapter dataadapter = new SqlDataAdapter(sql, connection);using (DataTable dt = new DataTable())
    {
        dataadapter.Fill(dt);

        //Set AutoGenerateColumns False
        dataGridView1.AutoGenerateColumns = false;

        //Set Columns Count
        dataGridView1.ColumnCount = 6;

        //Add Columns

        dataGridView1.Columns[0].Name = "Esercizio";
        dataGridView1.Columns[0].HeaderText = "Esercizio";
        dataGridView1.Columns[0].DataPropertyName = "Esercizio";

        dataGridView1.Columns[1].Name = "Serie";
        dataGridView1.Columns[1].HeaderText = "Serie";
        dataGridView1.Columns[1].DataPropertyName = "Serie";

        dataGridView1.Columns[2].HeaderText = "Ripetizioni";
        dataGridView1.Columns[2].Name = "Ripetizioni";
        dataGridView1.Columns[2].DataPropertyName = "Ripetizioni";

        dataGridView1.Columns[3].Name = "Recupero";
        dataGridView1.Columns[3].HeaderText = "Recupero";
        dataGridView1.Columns[3].DataPropertyName = "Recupero";

        dataGridView1.Columns[4].Name = "Time Under Tension";
        dataGridView1.Columns[4].HeaderText = "Time Under Tension";
        dataGridView1.Columns[4].DataPropertyName = "Time_Under_Tension";

        dataGridView1.DataSource = dt;

        connection.Close();

        
    }

    curCombo_LoadedValues();
}

但是我得到了这个错误“没有强制参数发送器的参数。。。

我怎样才能正确调用它?

第二个问题是,当我像这样填充一些dgv列时,组合框停止正常工作,我在组合框上得到一个错误异常:

dataGridView1.Rows.Add(7);
            Random rnd = new Random();
            
            dataGridView1.Rows[0].Cells[1].Value = 3;
            dataGridView1.Rows[0].Cells[2].Value = rnd.Next(1, 13);
            dataGridView1.Rows[0].Cells[3].Value = 1;
            dataGridView1.Rows[0].Cells[4].Value = 201;
            
            dataGridView1.Rows[1].Cells[1].Value = 2;
            dataGridView1.Rows[1].Cells[2].Value = rnd.Next(1, 13);
            dataGridView1.Rows[1].Cells[3].Value = 1;
            dataGridView1.Rows[1].Cells[4].Value = 201;
            
            dataGridView1.Rows[2].Cells[1].Value = 3;
            dataGridView1.Rows[2].Cells[2].Value = rnd.Next(1, 13);
            dataGridView1.Rows[2].Cells[3].Value = 1;
            dataGridView1.Rows[2].Cells[4].Value = 201;
            
            dataGridView1.Rows[3].Cells[1].Value = 4;
            dataGridView1.Rows[3].Cells[2].Value = rnd.Next(1, 13);
            dataGridView1.Rows[3].Cells[3].Value = 1;
            dataGridView1.Rows[3].Cells[4].Value = 201;
            
            dataGridView1.Rows[4].Cells[1].Value = 5;
            dataGridView1.Rows[4].Cells[2].Value = rnd.Next(1, 13);
            dataGridView1.Rows[4].Cells[3].Value = 1;
            dataGridView1.Rows[4].Cells[4].Value = 201;
            
            dataGridView1.Rows[5].Cells[1].Value = 6;
            dataGridView1.Rows[5].Cells[2].Value = rnd.Next(1, 13);
            dataGridView1.Rows[5].Cells[3].Value = 1;
            dataGridView1.Rows[5].Cells[4].Value = 201;
            
            dataGridView1.Rows[6].Cells[1].Value = 7;
            dataGridView1.Rows[6].Cells[2].Value = rnd.Next(1, 13);
            dataGridView1.Rows[6].Cells[3].Value = 1;
            dataGridView1.Rows[6].Cells[4].Value = 201;

这是dgv现在的样子:dgv

这是我在组合功能停止正常工作后得到的错误(我单击但没有下拉菜单出现,或者如果我单击2-3次,随机选择一个项目,但在另一列中没有视频链接出现):

误差

共有2个答案

冀景明
2023-03-14

我混合了ComboBox和DatagridViewComboboxColumn。有一部分是你的错:)。

这里有一个包含事件的表单。由于CellValueChanged在单元格退出时触发,我添加了一个Dirty State事件来更新视频列。从设计器中,只需将数据网格放在表单中并确保名称相同。恕我直言,这3个事件至关重要

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            Init();
        }

        private void Init()
        {
            var list = new List<Exercise>() {
            new Exercise (){Name="Name1", Link= "Link1" },
            new Exercise (){Name="Name3", Link= "Link3" },
            new Exercise (){Name="Name4", Link= "Link4" },

            };

            var comboColumn = new DataGridViewComboBoxColumn() { Name = "ExerciseName", CellTemplate = new DataGridViewComboBoxCell() };
            comboColumn.DisplayMember = nameof(Exercise.Name);
            comboColumn.ValueMember = nameof(Exercise.Link);
            comboColumn.DataSource = list;
            
            dataGridView1.Columns.Add(comboColumn);
            dataGridView1.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Video" });
            dataGridView1.CellContentClick += DataGridView1_CellContentClick;
            dataGridView1.CellValueChanged += DataGridView1_CellValueChanged;
            dataGridView1.CurrentCellDirtyStateChanged += DataGridView1_CurrentCellDirtyStateChanged;
        }

        private void DataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
        {
            var currentCell = (sender as DataGridView).CurrentCell;
            if(currentCell.ColumnIndex == 0)
                dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
            
        }

        private void DataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex != 0)
                return;
            var comboCell = (dataGridView1.Rows[e.RowIndex].Cells[0] as DataGridViewComboBoxCell);
            var value = comboCell.Value;
            dataGridView1.Rows[e.RowIndex].Cells["Video"].Value = value;

        }

        private void DataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            
        }
    }

    public class Exercise
    {
        public string Name { get; set; }
        public string Link { get; set; }
    }
司马俊晖
2023-03-14

在发布的代码中,它显示了一个对DB的查询,以获取练习名称,并将这些名称作为项目添加到该列的“each”组合框单元格中。这很好,但是,没有关于“哪个视频”属于组合框项目列表中每个项目的信息。我将假设哪个视频与哪个练习相关的“关系”将涉及对DB的另一个查询。

如果是这种情况,那么很容易看到,当网格中的组合框发生更改时,您可以简单地查询数据库,以查找要用于所选练习的视频。这当然会奏效;然而,这会产生冗余问题。例如,假设用户在网格第1行的组合框中选择了“踢”。该代码查询数据库并获取“踢”视频的位置,并将“视频”单元格设置为该视频路径。随后,用户再次为其他行选择“踢”。这将重新查询数据库,以获得我们之前获得的相同数据。您希望避免不必要地查询数据库。

因此,考虑到这一点,避免不必要地重新查询数据库的更好方法似乎是,我们以某种方式将练习与练习使用的特定视频“结合”起来。您可以在表单加载时执行此操作一次。一旦你有了练习,然后循环每个练习并查询DB中的练习视频,并将其与练习相结合。一旦我们有了视频链接,我们就会“保存”这些信息。使用这种方法,您将不必为任何给定的练习重新查询数据库,因为我们已经为所有练习保存了该信息。

有无数种方法可以将练习与视频“结合”。一个可能的解决方案是创建一个具有这两个属性的类。让我们称这个类为< code>ExerciseAndVideo…它有两个属性,一个是练习文本的< code > string < code > Exercise ,另一个是为< code >练习定义视频路径的< code > string < code > Video 。这个简单的类可能看起来像…

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

这是将练习与特定的Video“结合”的一种方法。然后,我们可以列出练习和视频对象的列表,例如…

List<ExerciseAndVideo> ExerciseList;

然后,我们不能只将此列表用作组合框列的DataSource,但我们也可以使用此列表来轻松地判断“哪个”视频属于“哪个”练习。下面的示例使用了此策略。

如何在DataGdriView中实现这一点…

要记住的一件事是,DataGdriViewComboBoxcell与“常规”ComboBox是“不同的怪物”。例如;对于常规组合框,有一个名为…选择索引改变事件。当用户“改变”当前选择的组合框索引时,此事件会触发。另一方面,DataGdriViewComboBoxcell没有选择索引改变事件,我想你可能知道。网格没有此事件是有道理的,因为网格的组合框“列”中可能有MANY组合框。

幸运的是,即使< code > datagridview ComboBox cell 没有< code > selectedindex changed 事件,我们也可以将“单个”组合框单元格转换为< code>ComboBox(在本例中是正在编辑的组合框单元格),然后我们可以订阅该< code > ComboBox < code > selectedindex changed 事件。然后,我们只需等待< code > selectedindex changed 事件触发,然后用适当的视频链接更新视频单元格数据。

数据网格视图为此提供了一个特殊事件,称为...编辑控件显示。当用户开始“编辑”网格中的单元格时,将触发此事件。在此特定情况下,当用户单击组合框单元格并“开始”以更改单元格值时,将触发此事件。我们在这个事件中要做的只是简单地将该组合框单元格转换为常规组合框...,然后,订阅该组合框 SelectedIndexChanged 事件,我们将在下面实现。

策略是这样的…我们将创建一个“全局”< code>ComboBox变量,我们称之为< code>curCombo。当grids < code > editing control showing 事件触发时,我们看到编辑的单元格是一个“练习”单元格…然后我们将把网格中的组合框单元格转换为全局< code>curCombo变量。然后,我们将订阅组合框< code > selectedindex changed 事件。当用户“离开”单元格时,我们将取消订阅全局变量< code > curCombo < code > selectedindex changed 事件,以保持整洁。

因此,考虑到这一点,网格EditingControl Show事件可能如下所示…

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) {
  if (dataGridView1.Columns[dataGridView1.CurrentCell.ColumnIndex].Name == "Exercise") {
    curCombo = e.Control as ComboBox;
    if (curCombo != null) {
      curCombo.SelectedIndexChanged -= new EventHandler(curCombo_SelectedIndexChanged);
      curCombo.SelectedIndexChanged += new EventHandler(curCombo_SelectedIndexChanged);
    }
  }
}

显然,我们需要实现事件处理程序curCombo_SelectedIndexChanged。在这种情况下,我们知道以前,用户选择了一个组合框单元格,并将该单元格中的值更改为其他值。由于练习发生了变化,我们知道我们需要更改“视频”单元格。

同样,有许多方法可以做到这一点,但是,如果我们将网格的“练习”组合框列的DataSource设置为练习和视频对象的列表,那么我们应该能够直接从全局ComboBoxcurCombo中获取特定的练习和视频对象。这将告诉我们“哪个”视频要放在“视频”单元格中。这可能看起来像…

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

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

为了完成示例并将所有这些放在一起可能会产生如下内容…

List<ExerciseAndVideo> ExerciseList;
ComboBox curCombo;

public Form2() {
  InitializeComponent();
}

private void Form2_Load(object sender, EventArgs e) {
  ExerciseList = GetExerciseVideoComboBoxListFromDB();
  dataGridView1.Columns.Add(GetExcerciseComboBoxColumn(ExerciseList));
  dataGridView1.Columns.Add(GetLinkColumn());
  dataGridView1.CellLeave += new DataGridViewCellEventHandler(dataGridView1_CellLeave);
  dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);
}


private DataGridViewComboBoxColumn GetExcerciseComboBoxColumn(List<ExerciseAndVideo> exerciseData) {
  DataGridViewComboBoxColumn cbCol = new DataGridViewComboBoxColumn();
  cbCol.HeaderText = "Exercise";
  cbCol.Name = "Exercise";
  cbCol.DisplayMember = "Exercise";
  cbCol.DataSource = exerciseData;
  return cbCol;
}

private DataGridViewLinkColumn GetLinkColumn() {
  DataGridViewLinkColumn col = new DataGridViewLinkColumn();
  col.HeaderText = "Video";
  col.Name = "Video";
  col.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
  return col;
}

private List<ExerciseAndVideo> GetExerciseVideoComboBoxListFromDB() {
  List<ExerciseAndVideo> exerciseList = new List<ExerciseAndVideo>();
  exerciseList.Add(new ExerciseAndVideo { Exercise = "Crosses", Video = @"C:/somepath/Crosses.htm/" });
  exerciseList.Add(new ExerciseAndVideo { Exercise = "Kickback", Video = @"C:/somepath/Kickback.htm" });
  exerciseList.Add(new ExerciseAndVideo { Exercise = "Leg Extensions", Video = @"C:/somepath/LegExtensions.htm" });
  exerciseList.Add(new ExerciseAndVideo { Exercise = "Crunches", Video = @"C:/somepath/Crunches.htm" });
  exerciseList.Add(new ExerciseAndVideo { Exercise = "Pushups", Video = @"C:/somepath/Pushups.htm" });
  return exerciseList;
}

如果网格有数据源怎么办?

当网格没有数据源时,这将按预期工作。但是,如果网格有一个数据源,并且数据源中的一个列/属性被绑定到我们的“练习”组合框列,那么,将会发生什么…就是在数据被加载后,组合框应该显示正确的练习,但是,所有的视频单元格将保持为空。这显然是因为加载数据时不会触发网格事件。

因此,在这种情况下,您需要一个方法来遍历网格中的所有行,检查该行的练习值,然后将视频单元格值设置为正确的视频链接。因为您没有说明网格是否有数据源,所以我假设这就是您所需要的。如果有数据源,我建议您检查每个“练习”以确保数据中的“练习”在组合框项目列表中,如果一个或多个“练习”在组合框列项目列表之外的数据中,那么当您试图设置网格数据源时,您将得到网格< code>DataError。

我希望这是有道理的。

编辑...数据加载到网格后设置视频单元格的示例。

private void SetVideoCellsAfterDataLoad() {
  foreach (DataGridViewRow row in dataGridView1.Rows) {
    if (!row.IsNewRow && row.Cells["Exercise"].Value != null) {
      foreach (ExerciseAndVideo eav in ExerciseList) {
        if (row.Cells["Exercise"].Value.ToString() == eav.Exercise) {
          row.Cells["Video"].Value = eav.Video;
          break;
        }
      }
    }
  }
}
 类似资料:
  • 我有一些组合框,它们在表单中具有预定义的值。但是,当用户提交表单并且我使用以下方法重置时,它工作正常: 这将在大多数区域完美地重置表单,并且组合框将再次用预定义的值重新填充,但是,如果您将值保持在新表单中并再次提交,您将收到一个“无法读取空的属性'0'”错误 我如何预填充值: 为避免此错误,用户当前需要做的是在组合框中重新选择当前选择的内容。如果我回答了以下问题之一,我觉得我可以避免这个问题: A

  • 问题内容: 我想使用css在html中的选择选项之间添加某种空间(填充,边距或其他)。我已经尝试使用类似的东西: 但是没有用。我已经读过,这是可以做到的,但在IE中不起作用。无论如何,即使它无法在IE中运行,我也希望它可以在其他浏览器中运行。 PS:当前正在使用Chrome 问题答案: 选择选项的样式非常有限,因为要在操作系统中的所有应用程序之间保持一致性和一致性,因此浏览器应限制某些基本元素的样

  • 我看到了许多类似问题的答案,人们说为了获得组合框中加载的项目的值,需要使用 但这种东西不起作用…… 这是我所拥有的…… 我从表中选择了Code1和Code2,我希望能够显示Code1,当被选中时,我希望能有Code2的值,但对于displayMember和ValueMember,我看不到任何结果。 编辑:这是我的所有代码: 暗淡的行=dt. Load(com. Ex 错误提示:表达式不产生值 编辑

  • 问题内容: 有没有一种方法可以填充JavaFX 或枚举的所有枚举? 这是我尝试的: 在另一个类中,我试图填充一个: 但是我得到一个错误: 我显然也遇到了同样的问题。 问题答案: 如果setItems需要一个ObservableList,则必须给它一个而不是一个数组。 试试这个: 编辑:James_D(请参阅注释)的解决方案是首选的解决方案:

  • 说到编程或java,我只是一个完全的初学者。所以一开始,我的计划是使用JavaFX(结合场景构建器)创建一个窗口,在那里我有一个按钮,可以引导我进入另一个窗口,在那里我有一个组合框。我谷歌了几个小时,想找到一种方法来填充组合框,但我找到的所有解决方案都不适合我。这就是为什么我认为我在这里犯了一些错误,我希望你能以某种方式帮助我。或者在列表中给我一个提示,我应该学习/阅读什么才能自己找到解决方案。首

  • 本文向大家介绍基于jQuery的表单填充实例,包括了基于jQuery的表单填充实例的使用技巧和注意事项,需要的朋友参考一下 如下所示: 以上这篇基于jQuery的表单填充实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊教程。