【问题标题】:Passing all items to another Form将所有项目传递给另一个表单
【发布时间】:2018-09-13 19:57:03
【问题描述】:

我将数据网格中的 variás 选择项传递给另一个表单,但是我需要第二个表单只打开一次。我把 Form 调用放在

    foreach (DataGridViewRow row in dgvcontasreceber.SelectedRows)
    {

       SqlConnection conConexao1 = clsdb.AbreBanco();
       SqlCommand cmd1 = new SqlCommand("select dbo.empresas.id, dbo.empresas.razao_social from empresas inner join dbo.pessoa_empresa on dbo.pessoa_empresa.empresa_id = dbo.empresas.id inner join dbo.pessoa on dbo.pessoa.id = dbo.pessoa_empresa.pessoa_id where dbo.pessoa.id ='" + lblid.Text + "'", conConexao1);
       SqlDataReader dr1 = cmd1.ExecuteReader();

        if (dr1.HasRows == true)
        {
            if (dr1.Read())
            {
               var item = new clsItens
               {
                  PessoaId = txtid.Text,
                  EmpresaId = int.Parse(dr1[0].ToString()),
                  RazaoSocial = dgvcontasreceber[0, linhaAtual].Value.ToString()
               };

               items.Add(item);
             }
         }

         dr1.Close();
         cmd1.Clone();
         conConexao1.Close();

   }
   FormRecebimento abrir = new FormRecebimento(items);
   abrir.ShowDialog();

【问题讨论】:

  • 有什么问题?期望的结果是什么?
  • 问题是你多次打开第二个表单,我希望它只打开一次但传递所有的foreach数据。
  • 但是您的 FormRecebimento 只能接受 1 行数据,它将如何显示所有行的数据?
  • 这是真的,我试图通过一个 prorem 数组,即使我正在传递一个值。这就是为什么我想知道如何转到另一种形式。
  • 您必须更改您的 FormRecebimento 以接受多行。然后您可以将所有行传递给表单,您将不再需要 foreach 循环。但是,如果您的 FormRecebimento 必须显示一组行而不是单个行,则它的外观必须非常不同。

标签: c# winforms foreach


【解决方案1】:

正如第一个答案所说,您需要找到一种方法让 FormRecebimento 接收一个集合(可以是数组、列表、IEnumerable 等),并根据您的需要在表单中使用这些值。

也许你可以从中得到一些启发:

class Item
{
    public string PessoaId { get; set };
    public int EmpresaId { get; set };
    public string RazaoSocial { get; set };
}

class FormRecebimento
{
    private List<Item> items;

    public FormRecebimento(List<Item> items)
    {
        this.items = items;
        this.initialize();
    }

    private void initialize()
    {
        /* Iterate over Item list and set the values you want
        pessoaid = int.Parse(txtid.Text);
        id_empresa = int.Parse(dgvcontasreceber[16, linhaAtual].Value.ToString());
        idrec.Text = dgvcontasreceber[0, linhaAtual].Value.ToString();
        */
    }
}

//... 

List<Item> items = new List<Item>();

foreach(DataGridViewRow row in dgvcontasreceber.SelectedRows)
{

   SqlConnection conConexao1 = clsdb.AbreBanco();
   SqlCommand cmd1 = new SqlCommand("select dbo.empresas.id, dbo.empresas.razao_social from empresas inner join dbo.pessoa_empresa on dbo.pessoa_empresa.empresa_id = dbo.empresas.id inner join dbo.pessoa on dbo.pessoa.id = dbo.pessoa_empresa.pessoa_id where dbo.pessoa.id ='" + lblid.Text + "'", conConexao1);
   SqlDataReader dr1 = cmd1.ExecuteReader();

   if (dr1.HasRows == true)
   {
      if (dr1.Read())
      {
         var item = new Item
         { 
            PessoaId = txtid.Text, 
            EmpresaId = int.Parse(dr1[0].ToString()),
            RazaoSocial = dgvcontasreceber[0, linhaAtual].Value.ToString()
         }
         items.add(item);
      }
   }

   dr1.Close();
   cmd1.Clone();
   conConexao1.Close();
}

FormRecebimento abrir = new FormRecebimento(items);
abrir.ShowDialog();

我真的不能在变量名称上使用正确的“标签”,因为我不太了解您的代码,所以我真的建议您看看互联网上的“清洁代码”资料,我确定对你有很大帮助:)

提示:http://www.macoratti.net/17/05/c_codlimp1.htm(ptBR,我相信你也会说葡萄牙语)

【讨论】:

  • 当我在 Form Receive 中初始化计数器时,出现错误提示:错误 CS0051 Inconsistent Accessibility: Parameter type "List " is less access than the "FormRecebimento.FormRecebimento(List)"
  • docs.microsoft.com/pt-br/dotnet/csharp/language-reference/… 我相信将类设置为“public”应该可以解决这个问题,例如:“public class Item”
  • 所以是FormReception调用转换的错误,也就是不识别对象Item
  • 查看无法从“System.Collections.Generic.List”转换为“System.Collections.Generic.List”的错误
  • 几乎可以工作了,问题出在这一行:dgvcontasreceber [0, currentLine] .Value.ToString () 总是取最后一个的值。我应该怎么做才能获得每个选定项的值?
【解决方案2】:

首先你没有使用SQL安全方式。

第二件事是你创建一个具有变量类型的表单实例,比如说int,然后每次在 foreach 循环中覆盖该变量。

我现在将为您编写完成的代码,因为这段代码完全是一团糟。

首先创建新的class,看起来像这样:

public YourNewClass
{
    public int Id { get; set; }
    public string razao_social { get; set; } //I am guessing this one is string in your database

    public YourNewClas()
    {
    }
}

现在在您要打开的新表单 (FormRecebimento) 中创建此变量

public List<YourNewClass> listOfMyNewClass;

现在你现在的代码重写如下:

FormRecebimento abrir = new FormRecebimento();
foreach(DataGridViewRow row in dgvcontasreceber.SelectedRows)
{
    using(SqlConnection conConexao1 = clsdb.AbreBanco()) //Use using since it will dispose of connection automatically after it finishes using it
    {
        conConexao1.Open(); // you do not have this line so maybe it is inside your function but not sure so i put it here
        using(SqlCommand cmd1 = new SqlCommand("select dbo.empresas.id, dbo.empresas.razao_social from empresas inner join dbo.pessoa_empresa on dbo.pessoa_empresa.empresa_id = dbo.empresas.id inner join dbo.pessoa on dbo.pessoa.id = dbo.pessoa_empresa.pessoa_id where dbo.pessoa.id = @ID", conConexao1))
        {
            cmd1.Parameters.AddWithValue("@ID", lblid.Text); //Use parameters when building SqlCommand since it is safer way

            SqlDataReader dr1 = cmd1.ExecuteReader();

            if (dr1.HasRows == true) // I am never using this one but just if(dr1.Read()) or while(dr1.Read()) and never had problem but i left it there  for you
            {
                if (dr1.Read())
                {
                    //We create new object type of your custom class and add it to new forms (which we created but haven't shown yet) list
                    abrir.listOfMyNewClass.Add(new YourNewClass{ Id = Convert.ToInt32(dr1[0]), razao_social = dr1[1].ToString();
                }
            }
        }
    }
    abrir.ShowDialog();
}

此代码将创建您的新表单 OUTSIDE FOREACH LOOP(因此只有一次),该表单将具有名为 listOfMyNewClass 的公共可访问变量,其类型为 List&lt;MynewClas&gt;

然后在 FOREACH 循环内部,我们将使用 Add() 方法在新表单中填充 listOfMyNewClass(因此我们不会每次都覆盖该变量)

然后在 OUTSIDE FOREACH LOOP 中,我们将显示新创建的表单,其中填充了 List&lt;YourNewClass&gt; listOfMyNewClass

要在新表单中操作该变量,只需阅读有关 System.Collections.Generic.List here 的所有内容,如果您想将该列表用作 DataTable,请查看我的答案 here

【讨论】:

  • 这部分我没看懂:` open.listOfMyNewClass.Add (new YourNewForm {Id = Convert.ToInt32 (dr [0]), social_role = dr [1] .ToString ();` 为什么我们是否必须创建一个新表单?“博士”是从哪里来的?
  • @Renato 对不起。是从头开始的。它应该是dr1 而不是dr。关于open.ListOfMyNewClass..... 在我的代码中我没有使用open 而是abrir(名称使用称为你的对象,这是你新创建的表单)
  • 偶用对象到类的转换错误。
  • 错误 CS1503 参数 1:无法从“Application.YourNewForm”转换为“Aplication.YourNewClass”
  • 在这部分代码中使用YourNewForm 插入YourNewForm。书写错误。还要重命名类。这些只是我的名字,所以你会更好地理解。
【解决方案3】:

目前,FormRecebimento 需要一个 pessoaid、一个 id_empresa 和一个 idrec 才能工作。如果必须将多个值传递给表单,则必须将这些属性替换为 IEnumerable&lt;DataGridViewRow&gt; 类型的新属性。如果我们将这个新属性称为 inputRows,那么您的代码将如下所示:

FormRecebimento abrir = new FormRecebimento();
abrir.inputRows = dgvcontasreceber.SelectedRows;
abrir.ShowDialog();

如何实现 inputRows 的显示超出了本问题的范围,但至少这应该让您朝着正确的方向开始。

【讨论】:

  • 在另一种形式中我创建了 public IEnumerable inputRows ;,但是第一种形式中的转换错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-01
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多