очистить datagridview дубликаты строк и сохранить уникальные строки - PullRequest
0 голосов
/ 20 ноября 2018

, поэтому при заполнении моего представления данных я обычно делаю что-то вроде

    public void FillTable(CoBRAMetaField[] metaFields)
    {
        dataGridView.Rows.Clear();

        // do something with metaFields
    }

Важно:

  • CoBRAMetaField - это объект сИдентификатор и прочее

  • Каждая строка в сетке содержит объект метаполя

Моя сетка заполнена правильно (извините, язык немецкий)

enter image description here

Когда я заполняю сетку в другой раз, я хочу удалить только строки с метаполями, которых нет в новом массиве metaFields.Мне нужно такое поведение, потому что, когда пользователь выбрал значение для этой строки, я не хочу, чтобы оно удалялось и создавалось заново, потому что затем выбранное значение также удаляется.

Я придумал это

    public void FillTable(CoBRAMetaField[] metaFields)
    {
        for (int i = 0; i < dataGridView.Rows.Count; i++) // loop through the grid rows
        {
            double metaFieldID = (dataGridView.Rows[i].Cells[0].Tag as CoBRAMetaField).ID; // get the ID from the row metaField

            if (metaFields.Any(field => field.ID == metaFieldID)) // Does it exist?
                metaFields = metaFields.Where(field => field.ID != metaFieldID).ToArray(); // Remove it from the new array
            else // it doesn't exist
                dataGridView.Rows.Remove(dataGridView.Rows[i]); // remove the row
        }

        // Fill the grid with the remaining metaFields
    }

Первый запуск корректно инициализируется

enter image description here

при втором запуске происходит сбой, некоторые поля остаются пустыми

enter image description here

, когда я нажимаю кнопку в этом ряду, я получаю исключение нулевого указателя.Я получаю эту ошибку только при использовании «нового кода», так что я что-то упустил?Есть ли что-то, о чем я не думал?


Я приведу полный пример здесь

Сначала создайте DataGridView и Button наформа.Создайте файл для всех необходимых классов и возьмите этот фрагмент

https://pastebin.com/BFmr2ps9

После этого заполните код формы некоторыми тестовыми данными

https://pastebin.com/Yz84Akkj

и теперь настройте DataGridView логику

https://pastebin.com/qH6kZKZv

Я добавил

dataGridView.AllowDrop = false;
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.AllowUserToOrderColumns = false;
dataGridView.AllowUserToResizeRows = false;

, если вы просто хотите скопировать вставку, но вы также можете сделать это с помощьюдизайнер форм.Посмотрите на dataGridView.Rows.Clear();, это рабочий пример. Прокомментируйте и используйте приведенный выше код для проверки неверного примера

1 Ответ

0 голосов
/ 23 ноября 2018

Основная проблема в коде для добавления строк (взятых из ссылки):

// Fill the grid with the remaining metaFields
for (int i = 0; i < metaFields.Length; i++)
{
    MetaField currentMetaField = metaFields[i];

    dataGridView.Rows.Add(currentMetaField.Name, null);

    DataGridViewRow newRow = dataGridView.Rows[i]; // <-- Problem!

    DataGridViewCell metaFieldCell = newRow.Cells[0];
    metaFieldCell.Tag = currentMetaField;

    (newRow.Cells[1] as DataGridViewAllocationCell).Initialize(releaseSetupData);
}

В отмеченной строке вы предполагаете, что индекс добавленной строки такой же, как i, что верно, когда вы начинаете с пустой сетки, бит не при обновлении сетки и сохранении некоторых старых записей.

Правильный способ обработки - не принимать новый индекс строки - он возвращается Добавить метод:

int rowIndex = dataGridView.Rows.Add(currentMetaField.Name, null);

DataGridViewRow newRow = dataGridView.Rows[rowIndex];

Это решит исходную проблему из вопроса.

Существует также проблема в части удаления кода - *Цикл 1014 * пропустит проверку строк рядом с удаленными.В любое время, когда вы хотите выполнить итерацию какого-либо списка и удалить элементы во время итерации, используйте reverse for loop и RemoveAt:

for (int i = dataGridView.Rows.Count - 1; i >= 0; i--) // <--
{
    double metaFieldID = (dataGridView.Rows[i].Cells[0].Tag as MetaField).ID;

    if (metaFields.Any(field => field.ID == metaFieldID))
        metaFields = metaFields.Where(field => field.ID != metaFieldID).ToArray();
    else
        dataGridView.Rows.RemoveAt(i); // <--
}

Код удаления можно еще улучшить (в настоящее время выглядитнеэффективно с этими Any, Where + ToArray), но по крайней мере с вышеуказанными изменениями он будет работать правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...