C# 使用添加到多个编程创建的控件的事件

C# 使用添加到多个编程创建的控件的事件,c#,sql-server,winforms,C#,Sql Server,Winforms,我显示组成产品的项目库存,用户必须能够在选择产品后在DataGridView中为每个项目更新这些项目的大小和数量 我创建DataGridView和事件,允许以编程方式更新数据库,因为每个产品可以由1到5项组成 SqlCommand stockCommand; SqlDataAdapter stockAdapter; SqlCommandBuilder stockBuilder; DataSet stockDs; DataTable stockTable; private void Displa

我显示组成产品的项目库存,用户必须能够在选择产品后在DataGridView中为每个项目更新这些项目的大小和数量

我创建DataGridView和事件,允许以编程方式更新数据库,因为每个产品可以由1到5项组成

SqlCommand stockCommand;
SqlDataAdapter stockAdapter;
SqlCommandBuilder stockBuilder;
DataSet stockDs;
DataTable stockTable;

private void DisplayItems()
{
    string queryItems = "SELECT id_item, id_PF, Name, Type FROM Items WHERE id_PF = "+ PF_id + " AND Type = 'BE'";
    using (SqlConnection con = new SqlConnection(conStringLocal))
    {
        using (SqlCommand cmdStock = new SqlCommand(queryItems, con))
        {
        int i = 0;
        con.Open();
        SqlDataReader readerStock = cmdStock.ExecuteReader();

        while (readerStock.Read())
        {
            string itemName = readerStock["Name"].ToString();
        DisplayItemsStock(i, itemName);
        i++;
        }
    }
    }
}


private void DisplayItemsStock(int i, string item)
{
    DataGridView stock = new DataGridView();
    stock.KeyDown += new KeyEventHandler(stock_KeyDown);

    string queryItemStock = "SELECT id_stock, item_name, size, quantity FROM Stock WHERE item_name = '" + item + "'";
    SqlConnection con = new SqlConnection(conStringLocal);
    stockCommand = new SqlCommand(queryItemStock con);
    stockAdapter = new SqlDataAdapter(stockCommand);
    stockBuilder = new SqlCommandBuilder(stockAdapter);
    stockDs = new DataSet();
    stockAdapter.Fill(stockDs, "stock");
    stockTable = stockDs.Tables["stock"];
    con.Close();
    stock.DataSource = stockTable;

    panelStock.Controls.Add(stock);
}

private void stock_KeyDown(object sender, KeyEventArgs e)
{
    DataGridView stock = (DataGridView)sender;

    if (e.Keycode == Keys.Enter)
    {
    // Check different conditions and update if everything is good

    using (SqlConnection con = new SqlConnection(conStringLocal))
        {
        con.Open();
        stockAdapter.Update(stockTable);
        MessageBox.Show("Saved changes");
    }       
    }
}

Update命令仅在我需要对最后创建的DataGridView进行所有操作时才会对其执行。

我相信您遇到了这个问题,因为这些变量在您的
DataGridView中共享

SqlCommand stockCommand;
SqlDataAdapter stockAdapter;
SqlCommandBuilder stockBuilder;
DataSet stockDs;
DataTable stockTable;
例如,当为第一个项目创建
DataGridView
时,使用该项目的查询将
stockCommand
设置为新的
SqlCommand
。适配器、生成器、数据集和表也是从中创建的。当为下一个项目创建
DataGridView
时,问题就会出现。现在,将创建一个新的
stockCommand
对象,其中包含对下一项的查询。同样,适配器、生成器、数据集和表都被设置为下一项的新对象。他们不再使用第一项的查询

现在,当按下键事件发生时,它将使用
stockTable
stockAdapter
这两个选项,它们现在正在使用对最后一项的查询。因此,最后一项是唯一更新的项

通过为每个
DataGridView
创建并保留单独的命令、适配器、生成器、数据集和数据表变量,可以避免此问题。你可以用
字典
来做这件事,或者我用一个新类来做

public class StockItem
{
  private const string conStringLocal = "Data Source=TestDatabase.sqlite;Version=3;";

  private readonly SqlCommand stockCommand;
  private readonly SqlDataAdapter stockAdapter;
  private readonly SqlCommandBuilder stockBuilder;
  private readonly DataSet stockDs;
  private readonly DataTable stockTable;

  public DataGridView StockDataGridView { get; }

  public StockItem(string item)
  {
    StockDataGridView = new DataGridView();
    StockDataGridView.KeyDown += new KeyEventHandler(stock_KeyDown);

    string queryItemStock = "SELECT id_stock, item_name, size, quantity "
      + "FROM Stock WHERE item_name = '" + item + "'";
    SqlConnection con = new SqlConnection(conStringLocal);

    stockCommand = new SqlCommand(queryItemStock, con);
    stockAdapter = new SqlDataAdapter(stockCommand);
    stockBuilder = new SqlCommandBuilder(stockAdapter);
    stockDs = new DataSet();
    stockAdapter.Fill(stockDs, "Stock");
    stockTable = stockDs.Tables["Stock"];
    con.Close();
    StockDataGridView.DataSource = stockTable;
  }

  private void stock_KeyDown(object sender, KeyEventArgs e)
  {
    DataGridView stock = (DataGridView)sender;

    if (e.KeyCode == Keys.Enter)
    {
      // Check different conditions and update if everything is good
      using (SqlConnection con = new SqlConnection(conStringLocal))
      {
        con.Open();

        stockAdapter.Update(stockTable);
        MessageBox.Show("Saved changes");
      }
    }
  }
}
DisplayItems
功能保持不变。而
DisplayItemsStock
变成:

private void DisplayItemsStock(int i, string item)
{
  StockItem stockItem = new StockItem(item);
  panelStock.Controls.Add(stockItem.StockDataGridView);
}

我没有看到
DataGridView
控件被添加到表单的任何位置?@gunnerone我认为这与问题无关,我编辑了我的代码。@A.Petit-你应该阅读然后。