程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 一個十分詭異的NullReferenceException異常

一個十分詭異的NullReferenceException異常

編輯:關於.NET

看到標題大家可能會認為這個文章一定沒有太大的新意,無非是忘記初始化一類的問題,但是建議大家慢慢看下去,我擔保這個問題決非這麼無聊,希望給大家增加一些樂趣啊!

大家可以這樣重現這個問題:

1,在窗體上放置一個TabControl控件有2個頁(tabPage1,tabPage2),tabPage1的為當前頁。

2,在tabPage1上放置一個 DataGridView控件dgv1,tabPage2上放置一個DataGridView控件dvg2並且兩個DataGridView的 AutoSizeColumnsMode 屬性為Fill,設置好兩個DataGridView的數據源後(這裡大家可以自己設置一些數據源,保證有一列的數據就可以,設置數組等也可以)。

3,訂閱窗體的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時候沒有拋出NullReferenceException異常,這說明dgv2.Columns[0]不是null,經過監視窗口觀察,他的確不是null。

那到底什麼是null呢?大家可能認為我又會像過去的一些文章中用IL說明問題吧!

這回不用IL來說明,我們看看類庫中的源代碼:

DataGridViewColumn類的Width屬性是這樣定義的:

public int Width
{
 get
 {
  return this.Thickness;
 }
  set
  {
    this.Thickness = value;
  }
}

實際上也沒有做什麼,只是設置了基類DataGridViewBand的Thickness屬性,Thickness屬性定義如下:

internal int Thickness
{
             get
             {
                 if (this.bandIsRow && this.bandIndex > -1)
                 {
                     int height, minimumHeight;
                     GetHeightInfo(this.bandIndex, out height, out minimumHeight);
                     return height;
                 }
                 return this.thickness;
             }
             set
             {
                 int minimumThickness = this.MinimumThickness;
                 if (value < minimumThickness)
                 {
                     value = minimumThickness;
                 }
                 if (value > maxBandThickness)
                 {
                     if (this.bandIsRow)
                     {
                         throw new ArgumentOutOfRangeException("Height", SR.GetString(SR.InvalidHighBoundArgumentEx, "Height", (value).ToString(CultureInfo.CurrentCulture), (maxBandThickness).ToString(CultureInfo.CurrentCulture)));
                     }
                     else
                     {
                         throw new ArgumentOutOfRangeException("Width", SR.GetString(SR.InvalidHighBoundArgumentEx, "Width", (value).ToString(CultureInfo.CurrentCulture), (maxBandThickness).ToString(CultureInfo.CurrentCulture)));
                     }
                 }
                 bool setThickness = true;
                 if (this.bandIsRow)
                 {
                     if (this.DataGridView != null && this.DataGridView.AutoSizeRowsMode != DataGridViewAutoSizeRowsMode.None)
                     {
                         this.cachedThickness = value;
                         setThickness = false;
                     }
                 }
                 else
                 {
                     DataGridViewColumn dataGridViewColumn = (DataGridViewColumn) this;
                     DataGridViewAutoSizeColumnMode inheritedAutoSizeMode = dataGridViewColumn.InheritedAutoSizeMode;
                     if (inheritedAutoSizeMode != DataGridViewAutoSizeColumnMode.Fill &&
                         inheritedAutoSizeMode != DataGridViewAutoSizeColumnMode.None &&
                         inheritedAutoSizeMode != DataGridViewAutoSizeColumnMode.NotSet)
                     {
                         this.cachedThickness = value;
                         setThickness = false;
                     }
                     else if (inheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill && this.DataGridView != null)
                     {
                         if (dataGridViewColumn.Visible)
                         {
                             IntPtr handle = this.DataGridView.Handle;
                             this.DataGridView.AdjustFillingColumn(dataGridViewColumn, value);
                             setThickness = false;
                         }
                     }
                 }

                 if (setThickness && this.thickness != value)
                 {
                     if (this.DataGridView != null)
                     {
                         this.DataGridView.OnBandThicknessChanging();
                     }
                     this.ThicknessInternal = value;
                 }
             }
}

代碼太長了啊,我把和這個問題相關的代碼帖出來,把AutoSizeColumnsMode 屬性為Fill,會執行到這裡:

else if (inheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill && this.DataGridView != null)
                     {
                         if (dataGridViewColumn.Visible)
                         {
                             IntPtr handle = this.DataGridView.Handle;  //我認為異常是這行代碼拋出的,這由於你的dgv2所在的TabPage並沒有激活所以這時Handle為null,所以拋出了 NullReferenceException異常
                             this.DataGridView.AdjustFillingColumn(dataGridViewColumn, value);
                             setThickness = false;
                         }
                     }

這個異常是內部拋出的!

如下方法可以解決這個問題:

1,不要把AutoSizeColumnsMode 屬性為Fill,然後再自己設置列寬。

2,可以把dgv2所在的TabPage設置為激活狀態:

private void form1_Load(object sender, EventArgs e)
{
 this.tabControl1.SelectedIndex = 1;
 dgv1.Columns[0].HeaderText = "名稱";
 dgv1.Columns[0].Width = 120;
 dgv2.Columns[0].HeaderText = "名稱";
 dgv2.Columns[0].Width = 120;
}

3,在其他位置修改列寬,比如dgv2的DataBindingComplete事件中。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved