C# 多窗體之間方法呼叫
阿新 • • 發佈:2019-01-03
看似一個簡單的功能需求,其實很多初學者處理不好的,很多朋友會這麼寫:
知道錯在那裡嗎?錯在強依賴!如果父窗體與子窗體在同一個模組內看似沒有錯,因為這種反向引用在同一個模組內是可行的,但程式不能這麼寫,你把它寫死了!固化了!假設我們的專案不斷在擴充套件,需要將父窗體與子窗體分開在不同的模組,這段程式碼就完了!因為父窗體模組必須引用子窗體模組,而子窗體需要用到frmParent的類,又要引用父窗體的模組!這時構成了雙向引用,編譯不能通過,所以講程式寫死了!
有什麼辦法解除這種依賴關係呢?辦法是有的,就是使用介面解除依賴關係!
我們把程式改下:
主窗體的程式碼:
子窗體的程式碼:
實現思路:
frmParent窗體所在的模組依賴frmChildA所在模組,而frmChildA只依賴IMdiParent介面,這正是《敏捷軟體開發》中所講的依賴倒置原則。最後,我們把IMdiParent介面部署在一個Common模組內,實際上frmParent與frmChildA只需要依賴Common模組。
Source Code for VS2008:
//父窗體是是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: