• 一个十分诡异的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事件中。

  • 相关阅读:
    Java学习-008-判断文件类型实例
    Java学习-007-Log4J 日志记录配置文件详解及实例源代码
    Java学习-006-三种数据库连接 MySQL、Oracle、sqlserver
    Java学习-005-初学常用的几个经典循环控制源代码
    Selenium2学习-009-WebUI自动化实战实例-007-Selenium 8种元素定位实战实例源代码(百度首页搜索录入框及登录链接)
    TestNG学习-002-annotaton 注解概述及其执行顺序
    C#设计模式之一单例模式(Singleton Pattern)【创建型】
    C#设计模式之二十三解释器模式(Interpreter Pattern)【行为型】
    C#设计模式之二十二备忘录模式(Memento Pattern)【行为型】
    C#设计模式之二十一访问者模式(Visitor Pattern)【行为型】
  • 原文地址:https://www.cnblogs.com/xuefeng1982/p/1662561.html
Copyright © 2020-2023  润新知