C#中通过父窗口调用子窗口的问题

原创 2007年09月18日 20:44:00
 
C#在父窗口中调用子窗口的过程:
1、 创建子窗口对象
2、 显示子窗口对象
 
笔者的程序中,主窗体MainFrm通过菜单调用子窗口ChildFrm。在窗体中定义了子窗口对象,然后在菜单项点击事件中,加入了如下代码来创建和显示子窗口:
Private childFrm myChildFrm = null//定义子窗口对象
private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
{
        myChildFrm 
= new ChildFrm();//创建子窗口对象
        myChildFrm.Show();//显示子窗口
        myChildFrm.Focus();//使子窗口获得焦点
}
当点击菜单中的OpenChild项时,创建了子窗口并显示在最前面。此时如果关闭子窗口再点击菜单打开,不会有问题。但是如果子窗口没有关闭的情况下,再次点击菜单中的OpenChild项,则会再创建一个子窗口。两个子窗口具有相同的内容,这不是我们所希望看到的。
为此,对菜单项点击事件做如下改进:
private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
{
    
if(myChildFrm != null)
    
{
        myChildFrm.Show();
//显示子窗口
        myChildFrm.Focus();//使子窗口获得焦点
    }

    
else
    
{
        myChildFrm 
= new ChildFrm();//创建子窗口对象
        myChildFrm.Show();//显示子窗口
        myChildFrm.Focus();//使子窗口获得焦点
    }

}

这样修改的目的是:当子窗口对象存在时,直接显示子窗口。当子窗口不存在时,创建子窗口,然后再显示。
现在来检验效果:当第一次点击OpenChild菜单项时,创建子窗口并正确显示。不关闭子窗口的情况下再点击OpenChild菜单项,子窗口只显示了一个,说明按预期工作了。现在,我们关闭子窗口,再点击OpenChild菜单项,程序在运行到下面这个语句时出现“未处理 ObjectDisposedException”异常。
if(myChildFrm != null)
{
    myChildFrm.Show();//显示子窗口
错误信息:无法访问已释放的对象。对象名:“childFrm”。
这就让人奇怪了。如果子窗口没有被销毁,那它就应该能够正确显示。点击了关闭子窗口,显然应该子窗口已经销毁了,按理myChildFrm等于null,运行的时候应该直接运行else后面的语句块,为什么却进入了满足myChildFrm!=null的语句块呢?
其实,这个问题与C#的垃圾回收有关。垃圾回收器管理所有的托管对象,所有需要托管数据的.NET语言(包括 C#)都受运行库的垃圾回收器的制约。垃圾回收器可以确定运行垃圾回收的最佳时间,自动进行垃圾回收。然而垃圾回收的一个产物是:C#对象没有确定性毁坏。所以会出现子窗口对象已被销毁,但又不为null,故出现访问时产生“未处理 ObjectDisposedException”异常(来自于“从小处看C#.net垃圾回收”一文)。
如何解决这个题,有人提出:应该应该彻底回收Child所占的资源。并提供了解决方法(请搜索“从小处看C#.net垃圾回收”查看相关情况)。
其实,现在我们需要解决的问题仅仅是:子窗口已经被销毁,但对象却不为null。只需要对你窗口中的菜单点击事件函数进行简单修改就可以了。
private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
{
    
if(myChildFrm != null)
    
{
          
if(myChildFrm.IsDisposed)
                  myChildFrm 
= new ChildFrm();//
如果已经销毁,则重新创建子窗口对象
          myChildFrm.Show();
          myChildFrm.Focus();
     }

    
else
    
{
        myChildFrm 
= new ChildFrm();
        myChildFrm.Show();
        myChildFrm.Focus();
    }

}

前面这是按逻辑的方式进行思考的,显示子窗口和获得焦点两行是重复的,两个if语句也可以做一下简化。指定子窗口和父窗口的父子关系。最后的结果是这样:
private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
{
    
if(myChildFrm == null || myChildFrm.IsDisposed)
    
{  
        myChildFrm 
= new ChildFrm();
    }

    myChild..MdiParent = this; //建立父子关系

        myChildFrm.Show(); //显示子窗口
    myChildFrm.Focus();  //子窗口获得焦点
}
这样,就能够如我们如愿般调用子窗口了。
 

C# WinForm 在父窗体与子窗体之间互相调用变量或方法

【父窗体调用子窗体变量或方法】:         首先在父窗体下定义子窗体,如:SubForm subform1=new SubForm();         再将子窗体subform1中需要调用的变...
  • momojiang5
  • momojiang5
  • 2015年12月23日 10:04
  • 4130

C#子窗体调用主窗体中事件

很多人都苦恼于如何在子窗体中操作主窗体上的控件,或者在主窗体中操作子窗体上的控件。相比较而言,后面稍微简单一些,只要在主窗体中创建子窗体的时候,保留所创建子窗体对象即可。 下面重点介绍前一种,目...
  • ycs34082419900527
  • ycs34082419900527
  • 2015年07月16日 22:33
  • 1086

winform程序两个窗体间同步数据(三):建立父窗口与子窗口的父子关系(不使用线程)

一 问题: 1 可不可以不使用线程?  可以。需要建立父窗口和子窗口之间的父子关系。 2 如何建立父子关系? 在子窗体中增加一个类型为父窗口的属性(即ChildFrm类中设置 publ...
  • nocomment_84
  • nocomment_84
  • 2017年02月03日 12:29
  • 914

WinForm中一个窗体调用另一个窗体的控件和事件的方法(附带源码)

先申明下,此文适合和我差不多的菜鸟学习,没有什么高深知识点,不想耽误老鸟们的宝贵时间,如果有什么专业术语不对的还请指正啊。     最近进行WinCE的开发,第一次实际做C/S架构的项目,其中遇到很多...
  • qiujialongjjj
  • qiujialongjjj
  • 2012年11月27日 13:26
  • 37673

C# MDI编程中子窗体调用子窗体的问题

在MDI编程中,从父窗体调用了子窗体,会出现子窗体隶属父窗体。但当我们要从一子窗体调用另一个子窗体,并且,调用过后,这个被子窗体调用出来的子窗体,会出现隶属于父窗体的情况是什么实现的呢? 下面是针对...
  • zhu1991_
  • zhu1991_
  • 2016年12月07日 10:25
  • 1583

C# Winform同一子窗体只允许打开一次

最近在写一个小程序,遇到子窗口打开多次的情况,通过查找找到了解决办法,但是有写不尽人意,比如对子窗体最小化时的处理。 因此进行了优化得到如下代码,目前测试可能遇到的情况都完美解决,包括子窗体最小化: ...
  • kangkang621
  • kangkang621
  • 2015年11月05日 16:13
  • 893

WinForm设计之主窗体

 Author:水如烟  参考应用类代码和辅助类代码现在尝试做一个通用的主窗体.所谓通用,按我的理解,是尽可能的把常用功能实现在一个类上,应用时仅考虑实际需求.因为是尝试,所以这部分代码我就不贴上来了...
  • lzmtw
  • lzmtw
  • 2006年12月11日 11:48
  • 3196

vs2005 C# 主窗体和子窗体之间控件相互调用

  vs2005 C# 主窗体和子窗体之间控件相互调用最近工作用到了C#开发Form应用程序,其中用到了主窗体和子窗体之间控件的相互调用。查了一些资料,现在根据自己写的一个小示例总结如下。1.主窗体中...
  • zhangyuanlovelife
  • zhangyuanlovelife
  • 2007年11月09日 23:19
  • 4907

winform设置子窗体的办法

1、首先你先建立一个窗体,窗体名称自定,然后把该窗体的属性“IsMdiContainer”为ture,这是一个重要的属性,窗体设置了这个属性就表示这个窗体为多文档应用程序的主窗体,它将作为子窗体的容器...
  • killcwd
  • killcwd
  • 2016年01月07日 11:40
  • 2491

WinForm中如何实现嵌入form窗体(panel与子窗体)

今天在做项目时候遇到一个问题,窗体分为左右两部分,要求在左边栏点击按钮时,右边动态加载窗体 最后想到用panel实现,经历几次失败,并查找资料后,终于搞定 说明:如果多次切换需加入 panel...
  • duanwenzhi00
  • duanwenzhi00
  • 2015年07月05日 13:46
  • 1268
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#中通过父窗口调用子窗口的问题
举报原因:
原因补充:

(最多只允许输入30个字)