C# 子窗体中调用父窗体中的方法(或多窗体之间方法调用)

http://www.csframework.com/archive/2/arc-2-20110805-1771.htm


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

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模块。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值