简体   繁体   English

DataGridView 排序导致 NullReferenceException

[英]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.我想要一个 DataGridView,用户可以通过单击表标题对其进行排序。 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). DataGridViews 数据绑定到一个 DataView 并且数据的最后一行应该是 sum 行(此代码中没有实现 sum!),它需要始终是最后一行(换句话说,它需要是免排序)。

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.'问题:一旦我点击任何标题对表格进行排序 - 这按预期工作 - 当我更改任何单元格中的值(并且 CellValueChangedHandler 被调用)时,我得到一个 System.NullReferenceException: 'Object reference not set to an instance of一个东西。' 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.上面的一行我能够从完全相同的行(存储在变量 temp 中)获取值,但是一旦我尝试写入单元格,就会抛出异常。

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;
        }

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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