WinForms 開發中,父視窗與子視窗 (或同級視窗) 之間的資料交換是常見需求。本文系統整理三種主流模式,分析優缺點與適用場景,附完整程式碼範例。
在子視窗建構函式或公用方法中接收父視窗所需資料或控制項參考。
// 子視窗
public partial class ChildForm : Form
{
public ChildForm(string text, ArrayList list, TextBox txtRef, ParentForm parent)
{
InitializeComponent();
// 使用參數...
}
}
// 父視窗呼叫
var child = new ChildForm("標題", myList, txtBox, this);
child.ShowDialog();
| 參數類型 | 傳遞語意 | 雙向性 | 耦合度 |
|---|---|---|---|
| 值型別 (int, string...) | 單向值複製 | 否 | 低 |
| 參考型別 (List, Array, 自訂類別) | 共享同一物件 | 是 (修改內容可見) | 中 |
| 控制項參考 | 直接操作父視窗 UI | 是 | 高 (違反關注點分離) |
父視窗實例 (this) | 存取父視窗所有 public 成員 | 是 | 極高 (強耦合) |
評價:簡單直接,但易造成強耦合、難以單元測試、違反單一職責原則。適合極簡單對話框。
利用 Form.Owner 或 ShowDialog(this) 建立擁有關係,子視窗透過 (ParentForm)this.Owner 存取父視窗公用成員。
// 父視窗
var child = new ChildForm();
child.Owner = this; // 或 child.ShowDialog(this);
child.ShowDialog();
// 子視窗 Load 或按鈕事件
var parent = (ParentForm)this.Owner;
parent.SomePublicProperty = "新值";
// 或呼叫父視窗公用方法
parent.RefreshData();
優點:語意清晰 (擁有關係)、自動處理最小化/關閉聯動、不需在建構函式傳參。
缺點:子視窗仍需知道父視窗具體型別 (強型別耦合)、僅限單一父視窗。
子視窗定義事件,父視窗訂閱;或父視窗傳入回呼委派。雙方僅依賴委派簽章,不依賴具體型別。
// 子視窗
public partial class ChildForm : Form
{
public event Action<string> DataSubmitted; // 或自訂 EventArgs
private void btnSubmit_Click(object sender, EventArgs e)
{
DataSubmitted?.Invoke(txtInput.Text);
this.Close();
}
}
// 父視窗
var child = new ChildForm();
child.DataSubmitted += data => {
txtResult.Text = data;
// 更新其他狀態
};
child.ShowDialog();
優點:完全解耦、可多播 (多個訂閱者)、易測試 (Mock 事件)、符合 SOLID 原則。
缺點:稍多程式碼、需注意事件取消訂閱避免記憶體洩漏。
複雜系統建議引入 MediatR、EventAggregator (Prism) 或自訂 IMessageBus,實現視窗間零耦合通訊,支援跨執行緒、記錄、重試等橫切關注點。
| 場景 | 推薦模式 |
|---|---|
| 簡單 Modal 對話框,單向傳值 | 模式一 (建構函式) |
| 需雙向互動、父子關係固定 | 模式二 |
| 多視窗協作、需解耦、可測試 | 模式三 (事件/委派) |
| 大型專案、跨模組通訊 | 中介者/訊息總線 |
掌握三種模式並根據專案複雜度選型,能寫出可維護、可擴充的 WinForms 架構。