Значение null при записи из datagridview в xml

185
15 мая 2018, 08:30

На форме есть пустая DataGridView. Создаю для неё DataTable.

private void новыйToolStripMenuItem_Click(object sender, EventArgs e)
{
    DataTable dt = new DataTable();
    dt.Columns.Add(new DataColumn("Product"));
    dt.Columns.Add(new DataColumn("Prize"));
    dt.Columns.Add(new DataColumn("Count"));
    dataGridView1.DataSource = dt;
}

Ввожу в строку DataGridView данные и пытаюсь сохранить их в XML.

private void сохранитьToolStripMenuItem_Click(object sender, EventArgs e)
{
    DataTable dT = GetDataTableFromDGV(dataGridView1);
    DataSet dS = new DataSet();
    dS.Tables.Add(dT);
    SaveFileDialog save = new SaveFileDialog();
    save.Filter = "XML|*.xml";
    if (save.ShowDialog(this) == DialogResult.OK)
    {
        try
        {
            dS.WriteXml(save.FileName);
        }
        catch(Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }
}

Метод GetDataTableFromDGV

private DataTable GetDataTableFromDGV(DataGridView dgv)
{
    DataTable dt = new DataTable();
    foreach (DataGridViewColumn column in dgv.Columns)
    {
        if (column.Visible)
        {
            dt.Columns.Add();
        }
    }
    object[] cellValues = new object[dgv.Columns.Count];
    foreach (DataGridViewRow row in dgv.Rows)
    {
        for (int i = 0; i < row.Cells.Count; i++)
        {
            cellValues[i] = row.Cells[i].Value;
        }
        dt.Rows.Add(cellValues);
    }
    return dt;
}

При попытке открыть сохраненный XML

private void открытьToolStripMenuItem_Click(object sender, EventArgs e)
{
    OpenFileDialog open = new OpenFileDialog();
    if (open.ShowDialog(this) == DialogResult.OK)
    {
        string path = open.FileName;
        ds = new DataSet();
        ds.ReadXml(path);
        dataGridView1.DataSource = ds.Tables[0].DefaultView;
    }
}

Всегда получается, что нет последней Column. В методе GetDataTableFromDGV() указывает на ошибку NullReferenceException в строке:

cellValues[i] = row.Cells[i].Value;

Прочитал, что надо изначально задавать column в DataTable чтобы её избежать, но они уже заданы при создании. В чем может быть ошибка?

Answer 1

Выкиньте полностью метод GetDataTableFromDGV.

У вас привязан DataTable к DataGridView, вот его и берите:

var dt = (DataTable)dataGridView1.DataSource;

Ещё лучше - сделайте его полем класса (формы).

DataSet тоже можно полностью выкинуть. Я понимаю, почему вы его используете: не получалось читать данные иначе.

Исходя из вопроса и комментариев, я могу предположить, что в файл не записываются те колонки, в которых нет данных. Чтобы решить эту проблему, можно записывать схему вместе с данными. Одновременно решится проблема чтения без датасета.

Запись:

dt.WriteXml(path, XmlWriteMode.WriteSchema);

Чтение:

dt.ReadXml(path);
dataGridView1.DataSource = dt;

Обратите внимание: создавать локальные DataTable не нужно! Мы его сделали полем.

Напомню, что DataSet тоже не нужен.

Осталось исправить ещё одну строку кода, чтобы всё заработало - дать имя дататейблу при его создании:

dt = new DataTable("Products");

Это необходимо в отсутствие датасета.

READ ALSO
Не работает Binding для наследующего класса. WPF

Не работает Binding для наследующего класса. WPF

Пол дня выяснял, почему не биндятся элементы в ListView, но как решить ситуацию - не поймуС WPF работаю совсем немного

241
c# задача коммивояжера

c# задача коммивояжера

Решаю задачу коммивояжера методом ветвей и границВозникла загвоздка, она не столько связана с кодом, сколько с пониманием алгоритма

305
как сделать нейронную простейшую сеть с 1 входом и 1 выходом

как сделать нейронную простейшую сеть с 1 входом и 1 выходом

Мне надо научить сеть делать что-то типо мат функцийТ

180