Я хотел бы иметь 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), но как только я пытаюсь записать в ячейку, выдается исключение.
Вопрос : У кого-нибудь есть идея, почему я могу прочитать значение из ячейки, но получить исключение при записи в нее?