Сортировка DataGridView приводит к исключению NullReferenceException - PullRequest
1 голос
/ 29 апреля 2019

Я хотел бы иметь DataGridView, который может быть отсортирован пользователем, нажав на заголовок таблицы. Данные DataGridViews связаны с DataView, и последняя строка данных должна быть строкой суммы (сумма не реализована в этом коде!), Которая всегда должна быть последней строкой (другими словами, она должна быть освобождены от сортировки).

На основании этого ответа я реализовал следующий код в своем классе:

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

Проблема : После того, как я щелкнул любой заголовок, чтобы отсортировать таблицу - что работает должным образом - когда я изменяю значение в любой ячейке (и вызывается CellValueChangedHandler), я получаю System.NullReferenceException: 'В экземпляре объекта не задана ссылка на объект.' в линии

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

На одну строку выше мне удалось получить значение из той же строки (хранится в переменной temp), но как только я пытаюсь записать в ячейку, выдается исключение.

Вопрос : У кого-нибудь есть идея, почему я могу прочитать значение из ячейки, но получить исключение при записи в нее?

1 Ответ

1 голос
/ 29 апреля 2019

Попробуйте следующий код:

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

    }
}
...