這不是普通的「忘記初始化」問題。重現步驟:
TabControl,兩頁 tabPage1(預設)、tabPage2DataGridView (dgv1、dgv2),AutoSizeColumnsMode = FillForm_Load 設定欄寬:
private void form1_Load(object sender, EventArgs e) {
dgv1.Columns[0].HeaderText = "名稱";
dgv1.Columns[0].Width = 120;
dgv2.Columns[0].HeaderText = "名稱";
dgv2.Columns[0].Width = 120; // 拋出 NullReferenceException
}
HeaderText 設定成功,說明 dgv2.Columns[0] 不為 null。監視視窗確認物件存在。真正為 null 的是什麼?
查閱 DataGridViewColumn.Width 原始碼:
public int Width {
get { return this.Thickness; }
set { this.Thickness = value; }
}
實際設定基類 DataGridViewBand.Thickness。其 set 邏輯中,當 AutoSizeColumnsMode = Fill 且欄位可見時:
else if (inheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill && this.DataGridView != null) {
if (dataGridViewColumn.Visible) {
IntPtr handle = this.DataGridView.Handle; // ★ 關鍵行:Handle 為 null
this.DataGridView.AdjustFillingColumn(dataGridViewColumn, value);
setThickness = false;
}
}
結論:tabPage2 非作用中,dgv2.Handle 尚未建立 (為 IntPtr.Zero),存取 Handle 觸發內部例外,包裝為 NullReferenceException 拋出。
AutoSizeColumnsMode
this.tabControl1.SelectedIndex = 1; // 先啟用 tabPage2
dgv2.Columns[0].Width = 120;
dgv2.DataBindingComplete 事件中設定欄寬,此時 Handle 已建立非作用中控制項的 Handle 屬性為 IntPtr.Zero,內部程式碼若未檢查直接使用會拋出難以診斷的例外。操作控制項原生屬性前,確保其 Handle 已建立 是關鍵防禦性程式設計原則。