网上关于C#之间的窗体之间互相传值其实很坑的。主要有修改要被传递数值的窗体的构造函数,然而这种方法,如果你要做打开一个窗体,然后这个窗体输入完东西之后传递回去,根本就是不知道怎么实现。之后还有什么委托delegate事件event大法,这个虽然能够实现,但我表示自己看了老半天都没看懂这个C#神特性。
比如如下的例子,在Form1点击“修改”按钮,将打开Form2,Form2中有一个文本框,输入完东西,无论用户按回车还是点击确认按钮,都会将输入结果反馈到Form1的Label1上,如果用户点右上角的“关闭”按钮,则不反馈。
同时,注意到,无论是Form1点击“修改”按钮,Form2会在Form1的位置出现,Form2确定修改之后,Form1同样会去到Form2的位置。
这个例子主要的核心是显示如果在两个窗体之间传递数值。
解决方案包含的东西如下:
其中Form2.cs是在解决方案中新建的Windows窗体,Intent.cs是新建的一个C#类。
Intent.cs就是本解决方案的核心,仿造Android的在Activity传递数值的思想,搞一个Key-values的字典dict,这个字典,用于存放窗体与窗体之间传递的数值。dict左边的key用string,右边的values用Object,这样就是面对不同的数值传递都可以应付。同时将这个字典dict直接设置成public static,调用不用这么麻烦。
using System; using System.Collections.Generic; using System.Text; namespace FormPassValues { class Intent { public static Dictionary<string, Object> dict = new Dictionary<string, Object>(); } }
Form1.cs的代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace FormPassValues { public partial class Form1 : Form { public Form1() { InitializeComponent(); this.StartPosition = FormStartPosition.CenterScreen;//设置form1的开始位置为屏幕的中央 } private void button1_Click(object sender, EventArgs e) { Form2 form2 = new Form2();//声明要使用form2窗体 //将form1当前的位置压入Intent中的dict Intent.dict["form1_top"] = this.Top; Intent.dict["form1_left"] = this.Left; Intent.dict["form1_label1_text"] = label1.Text; if (form2.ShowDialog() == DialogResult.OK) {//这个判断,将会等到form2被关闭之后才执行,如果form2返回一个OK值 this.Top = (int)Intent.dict["form2_top"];//更新form1的位置 this.Left = (int)Intent.dict["form2_left"]; label1.Text = Intent.dict["form2_textbox1_text"] + "";//更新form1的内容 } } } }
具体的Form2.cs的代码如下,textbox1按下Enter确定输入是仿造《【C#】利用System.IO中的File类中的ReadAllText与WriteAllText输入输出小文件》(点击打开链接)的处理,这里不再赘述了。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace FormPassValues { public partial class Form2 : Form { public Form2() { InitializeComponent(); } private void Form2_Load(object sender, EventArgs e) { //在初始化的时候,取出Intent中的需要属性,更新自己的位置,同时更新textbox1的内容 this.Top = (int)Intent.dict["form1_top"]; this.Left = (int)Intent.dict["form1_left"]; textBox1.Text = Intent.dict["form1_label1_text"] + ""; textBox1.Focus();//设置焦点停留在textBox1中 textBox1.Select();//同时选中textBox1中的所有文本,必须先有焦点,再选中 } private void button1_Click(object sender, EventArgs e) { //关闭form2之间,将要传给form1的值压入Intent中的dict Intent.dict["form2_top"] = this.Top; Intent.dict["form2_left"] = this.Left; Intent.dict["form2_textbox1_text"] = textBox1.Text; this.DialogResult = DialogResult.OK;//同时设置返回值为OK,不设置的话,默认返回Cancel this.Close(); } private void textBox1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter)//一旦用户在输入过程中输入Enter { this.button1_Click(sender,e);//则执行button1“确定”按钮点击事件 } } } }
在窗体间互相传值,关键是理解,在form2.ShowDialog();之后,form1的代码是在这里中断、形成一个断点的,知道form2被关闭之后,代码才继续向下执行的。原理是与《【C#】文件选择对话框OpenFileDialog与下列列表ComboBox》(点击打开链接)一模一样的,因此自己定一个公有的Intent全局类就能够解决这个问题。
同时,这里再补充一下form2.ShowDialog();之后form2是个模态对话框,就是form2不关闭,form1不能进行任何操作。
如果单纯地form2.Show(),form2则与form1没有任何关系了,form2也将没有任何返回值,form1的代码也不会中断在form2.Show()。