• 一个十分诡异的NullReferenceException异常


    看到标题大家可能会认为这个文章一定没有太大的新意,无非是忘记初始化一类的问题,但是建议大家慢慢看下去,我担保这个问题决非这么无聊,希望给大家增加一些乐趣啊!
    大家可以这样重现这个问题:
    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事件中。
  • 相关阅读:
    【Vegas原创】解决System.Web.Extensions版本冲突方法
    【Vegas原创】GridView修改表头,并导出Excel(C#版)
    bdump,cdump,udump作用
    【Vegas原创】用正则表达式解决FCKEditor图片路径问题
    【Vegas改编】获取,更新web.config的值
    面向对象和面向过程的区别
    【Vegas原创】删除有内外键关系数据的方法
    提供css滤镜代码,变网页为黑白,为在地震中遇难的同胞哀悼
    【Vegas原创】将treeview父结点的链接改为折叠事件
    C#经典试题
  • 原文地址:https://www.cnblogs.com/xuefeng1982/p/1861546.html
Copyright © 2020-2023  润新知