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

//父窗体是是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. 【ML】Two-Stream Convolutional Networks for Action Recognition in Videos

    Two-Stream Convolutional Networks for Action Recognition in Videos & Towards Good Practices for ...

  2. JAVA常用工具类汇总

    一.功能方法目录清单: 1.getString(String sSource)的功能是判断参数是否为空,为空返回"",否则返回其值: 2.getString(int iSource ...

  3. (转)SqlDateTime 溢出。必须介于 1/1/1753 12:00:00 AM 和 12/31/9999 11:59:59 PM之间

    原因: 出现这种问题多半是因为你插入或者更新数据库时,datetime字段值为空默认插入0001年01月01日造成datetime类型溢出. 传给数据库表的时间类型值是null值.这里的null指的是 ...

  4. QT下opencv的编译和使用

    需要的文件 qt-opensource-windows-x86-mingw491_opengl-5.4.0.exe cmake-3.12.0-rc1-win64-x64.msi opencv-2.4. ...

  5. js数组的用法

    1.数组 - - 添加元素 arr.push('abc')  向数组尾部添加元素,返回值为数组的长度 arr.unshift('abc')  向数组头部添加元素,返回值为数组的长度 2.数组 - - ...

  6. [书摘]图解HTTP 状态码

    状态码类别: 1XX informational 信息性状态码 2XX Suess   成功状态码 3XX Redirection 重定向状态码 4XX Client error 客户端错误状态码 5 ...

  7. ArrayMap代码分析

    Java提供了HashMap,但是HashMap对于手机端而言,对内存的占用太大,所以Android提供了SparseArray和ArrayMap.二者都是基于二分查找,所以数据量大的时候,最坏效率会 ...

  8. 数组 this.setData快捷赋值

    let list=this.data.list; let listString = `{"list[${index}].sliderSure":${!list[index].sli ...

  9. NAT模式下VMware中CentOS7无法连接外网的解决方法

    故障现象 ----------------------------------------------------------------------------------------------- ...

  10. GROUP BY 聚合函数(max min sum avg count) 和HAVING的 使用

    重新复习一下这个都源自于我经常需要查的一个需求 “要找到表里面 出现了两次或者三次的某个字段” 现在假设有一张表字段是 +----+---------------------+------------ ...