C# 子窗体中调用父窗体中的方法(或多窗体之间方法调用)
C# 子窗体中调用父窗体中的方法(或多窗体之间方法调用)
看似一个简单的功能需求,其实很多初学者处理不好的,很多朋友会这么写: C# Code: //父窗体是是frmParent,子窗体是frmChildA //在父窗体中打开子窗体 frmChildA child = new frmChildA(); child.MdiParent = this; child.Show(); //子窗体调父窗体方法: //错误的调用!!!!!!!! (this.MdiParent as frmParent).ParentFoo(); //来源:C/S框架网(www.csframework.com) QQ:1980854898 知道错在那里吗?错在强依赖!如果父窗体与子窗体在同一个模块内看似没有错,因为这种反向引用在同一个模块内是可行的,但程序不能这么写,你把它写死了!固化了!假设我们的项目不断在扩展,需要将父窗体与子窗体分开在不同的模块,这段代码就完了!因为父窗体模块必须引用子窗体模块,而子窗体需要用到frmParent的类,又要引用父窗体的模块!这时构成了双向引用,编译不能通过,所以讲程序写死了! 有什么办法解除这种依赖关系呢?办法是有的,就是使用接口解除依赖关系! 我们把程序改下: C# Code: /// <summary> /// 主窗体接口 /// </summary> public interface IMdiParent { void ParentFoo(); } /// <summary> /// 子窗体接口 /// </summary> public interface IMyChildForm { void Foo(); } 主窗体的代码: C# Code: /// <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 } //来源:C/S框架网(www.csframework.com) QQ:1980854898 子窗体的代码: C# Code: /// <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(); } //来源:C/S框架网(www.csframework.com) QQ:1980854898 实现思路: frmParent窗体所在的模块依赖frmChildA所在模块,而frmChildA只依赖IMdiParent接口,这正是《敏捷软件开发》中所讲的依赖倒置原则。最后,我们把IMdiParent接口部署在一个Common模块内,实际上frmParent与frmChildA只需要依赖Common模块。 Source Code for VS2008:
参考文档:
Delphi程序调用C#.Net编译的DLL并打开窗体(详解) C# 动态编译及调用WebService的方法 C#设计模式-窗体基类模板方法定义 C#.Net 类的同名方法重载调用顺序 C# 调用API枚举窗体,根据标题还原窗体 通过反射,调用DLL程序集某个类的静态方法打开窗体 C#.NET 对象(字符串)转换常用扩展方法 C#.NET扩展的动态对象支持动态属性和方法以及Json格式与对象互转 C/S客户端Winform窗体调用WebApi接口(C# 实例) 通过.NET反射动态调用SetValue方法给属性PropertyInfo赋值 如何跟踪查看当前用户拥有指定菜单窗体的权限值(GetUserActions方法) 用户数据操作报告(frmOperateReport)窗体使用方法 C#调用类成员 C#异步操作等待窗体,异步多线程处理数据通用界面(frmThreadOperating) C#多线程异步处理数据通用界面窗体(frmThreadOperating)
其它资料:
什么是C/S结构? | C/S框架核心组成部分 | C/S框架-WebService部署图 | C/S框架-权限管理 | C/S结构系统框架 - 5.1旗舰版介绍 | C/S结构系统框架 - 功能介绍 | C/S结构系统框架 - 产品列表 | C/S结构系统框架 - 应用展示(图) | 三层体系架构详解 | C/S架构轻量级快速开发框架 | C/S框架网客户案例 | WebApi快速开发框架 | C/S框架代码生成器 | 用户授权注册软件系统 | 版本自动升级软件 | 数据库底层应用框架 | CSFramework.CMS内容管理系统 | |