【问题标题】:Sending data between 2 forms在 2 个表单之间发送数据
【发布时间】:2018-12-13 12:30:46
【问题描述】:

我有带有 datagridview 和一个按钮的 form1。当我单击一个按钮时,会打开一个新表单,其中有一个文本框和一个按钮。在此文本框中,我可以编写查询并单击按钮查询结果显示在 form1 datagridview 中。问题是它打开了 form1 的另一个实例,但我希望 form1 始终保持打开状态,并且根据 form2 中的查询输入,只有 datagridview 中的记录在更改。 form1 和 form2 都需要在调用时打开并激活。

这是我的代码:

//FORM 1
public Form1()
{
    InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
    var queryForm = new Form2();
    queryForm.Show(this);
}

//FORM 2
public Form2()
{
    InitializeComponent();
}

private SqlConnection Conn;

private void Form1_Load(object sender, EventArgs e)
{
    Conn = new SqlConnection(@"Data Source=srvr;Initial Catalog =db; User ID =user; Password =pass");


}

private void btnExecute_Click(object sender, EventArgs e)
{
    Form1 frm1 = new Form1();
    frm1.Show(this);
    frm1.Activate();

    SqlCommand cmd = new SqlCommand();
    cmd.Connection = Conn;
    cmd.CommandText = txtQuery.Text;

    try
    {
        Conn.Open();

        SqlDataReader reader = cmd.ExecuteReader();

        frm1.dataGridView1.Columns.Clear();
        frm1.dataGridView1.Rows.Clear();
        if (reader.HasRows)
        {
            DataTable schema = reader.GetSchemaTable();
            int field_num = 0;
            foreach (DataRow schema_row in schema.Rows)
            {
                int col_num = frm1.dataGridView1.Columns.Add(
                    "col" + field_num.ToString(),
                    schema_row.Field<string>("ColumnName"));
                field_num++;

                frm1.dataGridView1.Columns[col_num].AutoSizeMode = 
                    DataGridViewAutoSizeColumnMode.AllCells;
            }

            object[] values = new object[reader.FieldCount];

            while (reader.Read())
            {
                reader.GetValues(values);
                frm1.dataGridView1.Rows.Add(values);
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error executing command.\n" + ex.Message);
    }
    finally
    {
        Conn.Close();
    }
}

【问题讨论】:

  • 那么打开另一个创建的表单而不是实例的过程是什么?
  • 如果您的问题得到回答,请接受给定的答案 - meta.stackexchange.com/questions/5234/… - 如果您的问题没有得到回答,请通过编辑您的问题来说明您的问题
  • @RandRandom 抱歉,稍后我有更多时间会回复这个问题。

标签: c# winforms


【解决方案1】:

好吧,既然你打电话给Form1 frm1 = new Form1(); - 除了opens up another instance of form1,你还期待什么? - 为什么new Form1() 不应该产生另一个实例?

您需要获取已创建的Form1 的引用。

例如看这个 Find the open forms in c# windows application

当你找到它时,你可以激活它,例如:

var frm1 = Application.OpenForms[0];
//frm1.Show(this); <- don't need to call Show since its already open
frm1.Activate();

你也应该把你的btnExecute_Click改成这个。

private void btnExecute_Click(object sender, EventArgs e)
{
    var frm1 = Application.OpenForms[0] as Form1; //find `Form1` like you want, I only take [0]

    //always create a new instance of SqlConnection here and dispose it with the using Keyword
    //don't use a private field to try to keep the Connection, let the internal Connection pool handle that case
    using (var con = new SqlConnection(@"Data Source=srvr;Initial Catalog =db; User ID =user; Password =pass"))
    {
        try
        {
            con.Open();

            //clean up, Command/Reader with using keyword
            using (var cmd = con.CreateCommand())
            {
                cmd.CommandText = txtQuery.Text;
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    //read data
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error executing command.\n" + ex.Message);
        }
    }

    //should activate the `Form1` AFTER the job is done, you can consider if you only want to activate it if the previous Code didn't fail
    frm1.Activate();
}

不要真正了解您在“read_data”例程中所做的事情。

此代码块:

frm1.dataGridView1.Columns.Clear();
frm1.dataGridView1.Rows.Clear();
if (reader.HasRows)
{
    DataTable schema = reader.GetSchemaTable();
    int field_num = 0;
    foreach (DataRow schema_row in schema.Rows)
    {
        int col_num = frm1.dataGridView1.Columns.Add(
            "col" + field_num.ToString(),
            schema_row.Field<string>("ColumnName"));
        field_num++;

        frm1.dataGridView1.Columns[col_num].AutoSizeMode = 
            DataGridViewAutoSizeColumnMode.AllCells;
    }

    object[] values = new object[reader.FieldCount];

    while (reader.Read())
    {
        reader.GetValues(values);
        frm1.dataGridView1.Rows.Add(values);
    }
}

试试如果以下就足够了,把上面代码中我的注释“//read data”替换成这个:

frm1.dataGridView1.AutoGenerateColumns = true; //say to automatically create columns, based on the result inside the datatable
frm1.dataGridView1.Columns.Clear();
var dataTable = new DataTable();
dataTable.Load(dataReader); //load the SqlDataReader into the DataTable
frm1.dataGridView1.DataSource = dataTable; //set the dataGridView's DataSource to the dataTable

【讨论】:

  • 如何找到已创建表单的引用?
  • 不要真正明白你的问题,它明确指出Application.OpenForms 引用了你所有的开放表格。它是一个列表,您必须在其中找到您的Form1
  • 您的代码有效。已使用 var frm1 = Application.OpenForms["Form1"]as Form1; 来查找打开的 Form1。
【解决方案2】:

在 form1 中单击按钮时,您可以简单地打开 form2 的一个新实例并在那里完成您的工作,并在关闭时在 form1 中接收该值。或者您可以通过构造函数将 form1 的实例传递到 form2 并从 form2 更新 form1。例如:

var isFormClosed = false;
using(form1 frm = new form1())
{
   // do something here
   frm.ShowDialog();
   isFormClosed = true;
}

或者,如果您希望将 form1 的引用传递给 form2,

var isFormClosed = false;
using(form1 frm = new form1(this))
{
   // do something here
   frm.ShowDialog();
   isFormClosed = true;
}

在这里,在form2中,您可以简单地使用form1传递的引用来更新属性或网格。

【讨论】:

    猜你喜欢
    • 2019-07-20
    • 1970-01-01
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多