看似一个简单的功能需求,其实很多初学者处理不好的,很多朋友会这么写:

//父窗体是是frmParent,子窗体是frmChildA
//在父窗体中打开子窗体
frmChildA child = new frmChildA();
child.MdiParent = this;
child.Show(); //子窗体调父窗体方法:
//错误的调用!!!!!!!!
(this.MdiParent as frmParent).ParentFoo();

知道错在那里吗?错在强依赖!如果父窗体与子窗体在同一个模块内看似没有错,因为这种反向引用在同一个模块内是可行的,但程序不能这么写,你把它写死了!固化了!假设我们的项目不断在扩展,需要将父窗体与子窗体分开在不同的模块,这段代码就完了!因为父窗体模块必须引用子窗体模块,而子窗体需要用到frmParent的类,又要引用父窗体的模块!这时构成了双向引用,编译不能通过,所以讲程序写死了!

有什么办法解除这种依赖关系呢?办法是有的,就是使用接口解除依赖关系!

我们把程序改下:

/// <summary>
/// 主窗体接口
/// </summary>
public interface IMdiParent
{
void ParentFoo();
} /// <summary>
/// 子窗体接口
/// </summary>
public interface IMyChildForm
{
void Foo();
}

主窗体的代码:

/// <summary>
/// 主窗体,实现IMdiParent接口
/// </summary>
public partial class frmParent : Form, IMdiParent
{
public frmParent()
{
InitializeComponent();
} private void form1ToolStripMenuItem_Click(object sender, EventArgs e)
{
//打开子窗体
frmChildA child = new frmChildA();
child.MdiParent = this;
child.Show();
} private void menuCallFoo_Click(object sender, EventArgs e)
{
//调用子窗体的Foo()方法
Form activedChild = this.ActiveMdiChild;
if ((activedChild != null) && (activedChild is IMyChildForm))
(activedChild as IMyChildForm).Foo();
} #region IMdiParent 成员 public void ParentFoo()
{
MessageBox.Show("调用" this.GetType().FullName ".ParentFoo()方法!");
} #endregion
}

子窗体的代码:

/// <summary>
/// 子窗体,实现IMyChildForm接口
/// </summary>
public partial class frmChildA : Form, IMyChildForm
{
public frmChildA()
{
InitializeComponent();
} #region IMyChildForm 成员 public void Foo()
{
MessageBox.Show("调用" this.GetType().FullName ".Foo()方法!");
} #endregion private void btnParentFoo_Click(object sender, EventArgs e)
{
//调用父窗体的ParentFoo()方法
if ((this.MdiParent != null) && (this.MdiParent is IMdiParent))
(this.MdiParent as IMdiParent).ParentFoo();
} private void btnErrCall_Click(object sender, EventArgs e)
{
//错误的调用
(this.MdiParent as frmParent).ParentFoo();
}



实现思路:

frmParent窗体所在的模块依赖frmChildA所在模块,而frmChildA只依赖IMdiParent接口,这正是《敏捷软件开发》中所讲的依赖倒置原则。最后,我们把IMdiParent接口部署在一个Common模块内,实际上frmParent与frmChildA只需要依赖Common模块。

Source Code for VS2008:

C# 多窗体之间方法调用的更多相关文章

  1. 多窗体之间方法调用 z

    C# Code: /// <summary> /// 主窗体接口 /// </summary> public interface IMdiParent{   void Pare ...

  2. ASP.NET同页面内【用户控件与父页面】以及【用户控件与用户控件】之间方法调用

    在用户控件中,获取父页面的方法 1:方法没有参数(userInfor()) string userInfor = Convert.ToString(this.Page.GetType().GetMet ...

  3. .NET同页面内用户控件与父页面以及控件之间方法调用

    用户控件调用父页面的方法: //获得父页面 Page p =this.Parent.Page; Type pageType = p.GetType(); //父页面的方法名 MethodInfo mi ...

  4. MFC 不同窗体之间变量调用

    应用场景: (1)主对话框包含一个Tab控件,Tab控件用来切换显示若干子对话框,子对话框类的成员需要互相访问. (2)或者程序中包含多个类,各类之间需要互相访问. 方法1-定义指针成员变量: 详情参 ...

  5. Delphi窗体之间互相调用的简单问题

    问题是这样的,我的程序主窗口Form1上面有一个数据连接(ADOCONNECTION1)和ADOQUERY,然后还有一些数据感知组件用于浏览用的,我打算点击From1中的一个“修改数据”按钮,就弹出F ...

  6. Iframe之间及iframe与父窗体之间值的传递

    方法一:ScriptManager.RegisterClientScriptBlock(this,typeof(Page), "NoInformation", "wind ...

  7. c# 不同窗体之间传值和调用

    1.子窗体事件刷新父窗体界面值 子窗体定义委托和事件 //声明一个委托 public delegate void DisplayUpdateDelegate(string str); //声明事件 p ...

  8. C#一个窗体调用另一个窗体的方法

    一个窗体调用另一个窗体的方法:例如:窗体B要调用窗体A中的方法1.首先在窗体A中将窗体A设为静态窗体public static  FormA   m_formA; //设此窗体为静态,其他窗体可调用此 ...

  9. synchronized修饰的方法之间相互调用

    1:synchronized修饰的方法之间相互调用,执行结果为There hello  ..因为两个方法(main,hello)的synchronized形成了互斥锁.  所以当main方法执行完之后 ...

随机推荐

  1. Linux内核设计期中总结

    Linux内核设计期中总结 ● 知识点 一.计算机是如何工作的 计算机是按照冯·诺依曼存储程序的原理. 在执行程序时须先将要执行的相关程序和数据放入内存储器中,在执行程序时CPU根据当前程序指针寄存器 ...

  2. <<架构漫谈>>读后感

    今天按照老师的要求,看了架构漫谈1--9讲,觉得受益良多,以下是我得点点读后感: (一)什么是架构? 架构的英文是Architecture,从定义上看,架构好像是一个过程,也不是很清晰.下面从架构的缘 ...

  3. QT 子窗口退出全屏

    m_pWidget代表子窗口, 子窗口显示全屏: m_pWidget->setWindowFlags(Qt::Dialog); m_pWidget->showFullScreen(); 子 ...

  4. ajax跨域请求数据

    最近开始接触ajax的跨域请求问题,相比网上说的一大堆,我这里就说得比较浅显了. 关于为什么要跨域这个问题,实际的需求是当网站项目部署在一个域名上的时候,分域可以很好地解决网站卡顿问题(拥有多台服务器 ...

  5. 加载spring容器

    import org.springframework.context.ApplicationContext; import org.springframework.context.support.Cl ...

  6. PAT 1009 说反话

    https://pintia.cn/problem-sets/994805260223102976/problems/994805314941992960 给定一句英语,要求你编写程序,将句中所有单词 ...

  7. Eclipse版本列表

    https://wiki.eclipse.org/Older_Versions_Of_Eclipse http://blog.csdn.net/jaycee110905/article/details ...

  8. js Location

    window.location用來返回頁面的地址,并把頁面重定向新的頁面: location.pathname:返回當前的頁面地址和文件名 location.hostname:主機名 location ...

  9. 设计模式【PHP案例】

    内容来源: 波客 菜鸟教程 策略模式 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式. 在策略模式中,我们创建表示各种策略的对 ...

  10. Codeforces Round #418 (Div. 2) B. An express train to reveries

    time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...