C#WinForm窗体之间的相互操作

  程序员在.Net平台下进行WinForm应用程序开发过程中,经常会遇到窗体之间的相互传值或者其他的调用操作,这是在.Net平台上编写WinForm程序很重要的一个基础,网络上问及这方面的帖子特别多,我做了简单举例并将具体的方法做了一个总结。
  设计如下的两个窗体:
  From1中button1的功能代码相对简单:
  Form2 Frm2 = new Form2();
  Frm2.Show();
  Form2.textbox1.text=textbox1.text;   
  在输入最后的代码时有问题,系统会提示“窗体调用.Form2”并不包含“textbox1”的定义”,看From2中的定义文件中,有“private System.Windows.Forms.TextBox textBox1;”说明Form2窗体中的textbox1是私有的,对外不能访问,怎么办?改动访问属性,将“Private”改为“internal”(即在本程序集里可以访问)再运行,系统正常了。
   总结:可以通过改变窗体控件的访问属性来进行操作。
 
  系统将窗体控件的访问属性默认为私有,这样做是遵循了面向对象的封装原则,所以,我们还是将“internal”改回“Private”,那上面的问题怎么解决?
  既然是打开窗体就传值,那么在From2中声明一个构造函数就然后在From2窗体初始化的时候就传值就可以了,在From2中声明新的构造函数:
  public Form2(string SValue)
  {
            this.textBox1.Text = SValue;
  }
  在From1窗体的button1按钮的点击事件中写如下代码:
  Form2 Frm2 = new Form2(textBox1.Text);
  Frm2.Show();
  代码没有问题,运行时系统报告构造函数错误,原来From2(string SValue)的textbox1对象为空,那么就是说该代码运行于初始化事件之前【在窗体或者控件绘制图形或者其他操作时也会遭遇这样的问题,即在对象初始化之前进行类似操作当然会出现问题】,所以改动代码如下:
  public Form2(string SValue)
  {
            InitializeComponent();//加入初始化事件
            this.textBox1.Text = SValue;
  }
  运行,系统正常了。
   总结:可以定义一个传递对象并且在窗体的构造函数中接收传递对象来处理窗体的传值操作。

 
  现在处理Form1中的button2事件,它的作用是在Form2窗体打开的情况下改变该窗体中的textbox1的值。
  写代码时必须找到打开的窗体然后再赋值,因为对Frm2定义只在button1_Click方法体中存在,所以无法在本方法体中利用Frm2,那么是不是在把Frm2的作用域延伸到整个Form1窗体(在Form1中定义)就可以利用Frm2了。但是这个没有解决问题,关键在于Form2中的textbox1是私有的,所以,我们没有必要在Form1中定义对Form2的引用。
  找到目前打开的Form2窗体的实例对象,可以应用Application对象,它包含了一个集合对象OpenForms,通过检索它可以找到目前打开的窗体。
  textbox1 既然是私有的,那么我们可以通过定义属性来操作它,如下:
  public string Textbox1
  {
            get { return textBox1.Text; }
            set { textBox1.Text = value; }
  }
  那么Form1中的button2的点击事件代码可以这样写了:
  ((Form2)Application.OpenForms["Form2"]).Textbox1 =textBox1.Text;
  运行系统,正常。
  问题又来了,当你打开多个Form2实例对象窗体时,上面的代码只改变最先打开的那个,其他的没有反应。
  因为Application.OpenForms["Form2"])是按Form2名称检索【索引器】,检索到后就返回了,所以只有最先打开的Form2对象接收了操作,改动Form1中的button2的点击事件代码如下:
  foreach (Form Frm in Application.OpenForms)
  {
                if (Frm.Text == "Form2")
                {
                    ((Form2)Frm).Textbox1 = textBox1.Text;
                }
  }
  这样就可以对所有打开的Form2对象实例进行相同的操作了。
   总结:根据封装原则,通过属性来封装对象内的字段操作提高安全性,检索Application.OpenForms可以对系统目前打开的窗体进行操作。

 
  窗体传值是一个事件的改变触发另外一个方法或者动作,对于此类应用我们一般通过委托来实现。
  在Form2中写下如下代码:
  public delegate void MyDelegateChange(string Str);//定义委托
  public MyDelegateChange MyChange;//声明
  //定义动作
  private void MyChangeFunction(string Str)
  {
            textBox1.Text = Str;
  }
  在Form2的button2的点击事件中写下如下代码:
  MyChange = new MyDelegateChange(MyChangeFunction);
  在Form1的button2的点击事件中写下如下代码:
   Form2 Frm2 = new Form2();
   foreach (Form Frm in Application.OpenForms)
   {
                if (Frm.Text == "Form2")
                {
                    Frm2 = (Form2)Frm;
                }
   }
   Frm2.MyChange(textBox1.Text);
  运行系统,正常传值。
  我们还可以通过委托定义事件来处理。
  在Form2中写下入下代码:
  public delegate void MyDelegateChange(string Str);//定义委托
  public event MyDelegateChange OnMyChange;//声明事件
  public void Form2_OnMyChange(string Str)
  {
            //事件动作
            textBox1.Text = Str;
  }
  在Form1的button2的点击事件中写下如下代码:
  Form2 Frm2 = new Form2();
  Frm2.Form2_OnMyChange(textBox1.Text);
  运行,系统正常传值。
  总结:可以通过委托和事件来进行窗体之间的传值操作。

 
  其实,上面是秉承面向对象的原则来处理,看起来麻烦,如下方法可以随意地达到目的:
  Form Frm2 = new Form2();
  foreach (Form Frm in Application.OpenForms)
  {
                if (Frm.Text == "Form2")
                {
                    Frm2 = Frm;
                }
  }
  Frm2.Controls["textbox1"].Text = textBox1.Text;
  在写代码过程中,通过上面的方式我们只能操作控件共有的属性和方法,如果是控件特有的,可以通过引用的方式进行处理,假设Form2上面有个CheckBox1的控件,现在在Form1的Button2的点击事件中操作它,可以按如下的方式:
  CheckBox CB1=new CheckBox();
  CB1 = Frm2.Controls["checkBox1"] as CheckBox;
  CB1.Checked = true;
  比如,现在Form2窗体上有个名为button1的按钮,你希望触发它的点击事件,可以这样写:
  ((Button)Frm2.Controls["button1"]).PerformClick();
  总结:我们可以通过检索集合对象来进行窗体之间相互灵活的操作。

 
   网络上,对于对话框窗口的传值的问题也很多,解决办法是如果你想获取一个窗口的返回值,直接调用就可以。
  当然也可以通过如下方法来调用,比如在Form1中打开了Form2,点击Form2上面的按钮更改Form1上面的textBox1的值,可以如下写:
  this.Owner.Controls[“textbox1”].text=”123”;
  另外还有一些其他方法,比如:
  1、我们还可以通过API的调用来进行窗体之间的相互操作,只是现在已没有必要这样去做了;
  2、设置一个公用类来传参数,一般不可取;
  3、设置一个接口来传参数,缺少灵活性也不可取;
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值