首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

一個詭異的 NullReferenceException:DataGridView 在非作用中 TabPage 設定寬度失敗

     編輯:關於.NET

這不是普通的「忘記初始化」問題。重現步驟:

  1. 表單放 TabControl,兩頁 tabPage1(預設)、tabPage2
  2. 各頁放 DataGridView (dgv1、dgv2),AutoSizeColumnsMode = Fill
  3. 設定資料來源後,在 Form_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 拋出。

三種解決方案

  1. 移除 Fill 模式:改用固定欄寬或其他 AutoSizeColumnsMode
  2. 暫時切換至目標 TabPage:
    
            this.tabControl1.SelectedIndex = 1; // 先啟用 tabPage2
            dgv2.Columns[0].Width = 120;
            
  3. 延後設定:在 dgv2.DataBindingComplete 事件中設定欄寬,此時 Handle 已建立

教訓

非作用中控制項的 Handle 屬性為 IntPtr.Zero,內部程式碼若未檢查直接使用會拋出難以診斷的例外。操作控制項原生屬性前,確保其 Handle 已建立 是關鍵防禦性程式設計原則。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved