• C# 多窗体之间方法调用


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

    //父窗体是是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:
  • 相关阅读:
    android 图片特效处理之模糊效果
    android 图片特效处理之怀旧效果
    android图像处理系列之六-- 给图片添加边框(下)-图片叠加
    android图像处理系列之五-- 给图片添加边框(中)
    android图像处理系列之四-- 给图片添加边框(上)
    android图像处理系列之三-- 图片色调饱和度、色相、亮度处理
    Android学习笔记进阶18 之画图并保存图片到本地
    Android学习笔记进阶19 之给图片加边框
    HDU3572_Task Schedule(网络流最大流)
    再淡spring jdbc 连接池断开重连设置
  • 原文地址:https://www.cnblogs.com/zhaoshujie/p/9594776.html
Copyright © 2020-2023  润新知