WinForms 開發中,父視窗與子視窗互相存取控件是常見需求。子視窗操作父視窗相對較棘手,本文介紹兩種主流模式,並推薦符合封裝原則的最佳實踐。
在父視窗類別定義靜態欄位保存當前實例:
public partial class MainForm : Form
{
public static MainForm CurrentInstance = null;
public MainForm()
{
InitializeComponent();
CurrentInstance = this; // 建構函數中初始化
}
}
子視窗透過 MainForm.CurrentInstance 存取父視窗。
在子視窗定義私有欄位,透過建構函數接收父視窗:
public partial class ChildForm : Form
{
private readonly MainForm _parentForm;
public ChildForm(MainForm parentForm)
{
InitializeComponent();
_parentForm = parentForm;
}
}
父視窗建立子視窗時傳入 this:new ChildForm(this).Show();
許多開發者為了方便,將控件的 Modifiers 屬性改為 Public。這嚴重破壞封裝性,導致:
在父視窗提供受控的存取介面:
public partial class MainForm : Form
{
// 封裝按鈕文字
public string SubmitButtonText
{
get => btnSubmit.Text;
set => btnSubmit.Text = value;
}
// 封裝按鈕點擊邏輯
public void TriggerSubmitClick()
{
btnSubmit.PerformClick(); // 觸發點擊事件
}
// 封裝複雜操作
public void UpdateStatus(string message, Color color)
{
if (lblStatus.InvokeRequired)
{
lblStatus.Invoke(() => UpdateStatus(message, color));
return;
}
lblStatus.Text = message;
lblStatus.ForeColor = color;
}
}
| 維度 | 靜態單例 | 建構函數注入 |
|---|---|---|
| 適用場景 | 單一主視窗、全域存取 | 多子視窗、需解耦測試 |
| 生命週期管理 | 需手動清理避免記憶體洩漏 | 隨子視窗銷毀自然釋放 |
| 單元測試友善度 | 低(靜態狀態難以隔離) | 高(可注入 Mock 物件) |
| 推薦指數 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
結論:優先採用「建構函數注入 + 公開屬性/方法封裝」模式,兼顧封裝性、可測試性與維護性。靜態單例僅適用於簡單的單一主視窗架構。