简体   繁体   中英

DataGridView sorting leads to NullReferenceException

I would like to have a DataGridView that can be sorted by the user by clicking on the table header. The DataGridViews data is bound to a DataView and the last row of the data is supposed to be a sum row (the sum is not implemented in this code!) that needs to always be the last row (in other words, it needs to be exempt from sorting).

Based on this answer I implemented the following code in my class:

using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace PipelineManagement.Debug
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            tlp1.RowStyles.Clear();
            for (var i = 0; i < 1; i++)
            {
                tlp1.RowStyles.Add(new RowStyle(SizeType.Absolute, 200));
                var gbNew = new GroupBox();
                gbNew.Text = "gb" + i;
                gbNew.Size = new Size(tlp1.Size.Width - 2, 185);
                gbNew.Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom | AnchorStyles.Left;
                m_dgv = new DataGridView();
                m_dgv.Parent = gbNew;
                m_dgv.AutoSize = true;
                m_dgv.Location = new Point(5, 25);
                m_dgv.Size = new Size(gbNew.Size.Width - 10, gbNew.Size.Height - 70);
                m_dgv.Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Left;
                m_dt = new DataTable();
                for (var j = 0; j < 2; j++)
                {
                    var NewColumn = new DataColumn("Column" + j, typeof(Double));
                    m_dt.Columns.Add(NewColumn);
                }
                var k = 5;
                for (var j = 0; j < 5; j++)
                {
                    var NewRow = m_dt.NewRow();
                    NewRow[0] = Convert.ToDouble(k--);
                    m_dt.Rows.Add(NewRow);
                }
                m_dt.AcceptChanges();
                m_dgv.ColumnHeaderMouseClick += dgv_ColumnHeaderMouseClick;
                m_dgv.CellValueChanged += CellValueChangedHandler;
                m_dgv.DataSource = m_dt.DefaultView;

                tlp1.Controls.Add(gbNew);
            }
        }

        private void dgv_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            var col = m_dgv.Columns[e.ColumnIndex].Name;
            if (col != "")
            {
                if (m_Direction == ListSortDirection.Ascending)
                {
                    m_Direction = ListSortDirection.Descending;
                }
                else
                {
                    m_Direction = ListSortDirection.Ascending;
                }                
                sort_dgv(col, m_Direction);
            }
        }

        private void CellValueChangedHandler(Object sender, DataGridViewCellEventArgs e)
        {
            var temp = m_dt.Rows[0].Field<Double>(0);
            m_dt.Rows[m_dt.Rows.Count-1].SetField<Double>(0, m_dt.Rows[m_dt.Rows.Count - 1].Field<Double>(0) + 1);
        }

        private void sort_dgv(String ColumnName, ListSortDirection Direction)
        {
            if (!m_dt.Columns.Contains("sortMe"))
            {
                m_dt.Columns.Add("sortMe", typeof(Int32));
            }
            var dr = m_dt.Rows[m_dt.Rows.Count - 1];

            m_dt.DefaultView.Sort = "";
            for (int r = 0; r < m_dt.Rows.Count; r++)
            {
                m_dt.Rows[r]["sortMe"] = 0;
            }
            dr["sortMe"] = int.MaxValue;

            if (Direction == ListSortDirection.Descending)
            {
                m_dt.DefaultView.Sort = "sortMe," + ColumnName + " DESC";
            }
            else
            {
                m_dt.DefaultView.Sort = "sortMe," + ColumnName;
            }
            m_dt.Columns.Remove("sortMe");
        }

        private DataGridView m_dgv;
        private DataTable m_dt;
        private ListSortDirection m_Direction = ListSortDirection.Ascending;
    }
}

The problem : Once I clicked on any header to sort the table - which works as expected - when I change a value in any cell (and the CellValueChangedHandler gets called) I get a System.NullReferenceException: 'Object reference not set to an instance of an object.' in the line

m_dt.Rows[m_dt.Rows.Count-1].SetField<Double>(0, m_dt.Rows[m_dt.Rows.Count - 1].Field<Double>(0) + 1);

One line above I was able to get the value from exactly the same line (stored in variable temp) but as soon as I try to write to the cell the exception is thrown.

Question : Does someone have an idea why I can read the value from the cell but get an exception when writing to it?

Try following code :

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication44
{
    public partial class Form1 : Form
    {
        DataTable m_dt = new DataTable();

        public Form1()
        {
            InitializeComponent();

            m_dgv.CellValueChanged += CellValueChangedHandler;

            m_dt.Columns.Add("Col_A", typeof(double));
            m_dt.Columns.Add("Col_B", typeof(string));
            m_dt.Rows.Add(new object[] { 1 });

            m_dgv.DataSource = m_dt;
        }

        private void CellValueChangedHandler(Object sender, DataGridViewCellEventArgs e)
        {
            DataGridView dgv = sender as DataGridView;
            DataGridViewCellEventArgs arg = e as DataGridViewCellEventArgs;
            int row = arg.RowIndex;
            int col = arg.ColumnIndex;

            if (row >= 0 && row == dgv.Rows.Count - 2) //new row already added to DGV
            {
                if (row == 0)
                {
                    if (col != 0)
                    {
                        dgv.Rows[row].Cells[0].Value = 1;
                    }
                }
                else
                {
                    double temp = (double)dgv.Rows[row - 1].Cells[0].Value;
                    dgv.Rows[row].Cells[0].Value = temp + 1;
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            m_dt = m_dt.AsEnumerable().OrderBy(x => x.Field<string>("Col_B")).CopyToDataTable();
            m_dgv.DataSource = null;
            m_dgv.DataSource = m_dt;
        }

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM