本文轉載:http://www.csframework.com/archive/2/arc-2-20110805-1771.htm
文章側重點主要是討論“窗體”與“窗體”之間方法的調用,以及“MDI父窗體”與“Chilid子窗體”之間如何相互的調用方法。
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,子窗體是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();
}
///<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
///<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
///<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模塊。