Обновление привязок DataGridView к списку при удалении строки - PullRequest
4 голосов
/ 17 сентября 2009

У меня есть приложение WinForm с несколькими DataGridView, привязанными к спискам SortableBindingLists.

При некоторых обстоятельствах мне нужно программно удалить элемент из списка, к которому привязана сетка.

Я не могу заставить DGV распознать, что его данные изменились или, в частности, что в нем меньше строк. Я вызываю dataGridView1.Invalidate (), и он перерисовывает сетку, но пытается перерисовать столько строк, сколько было раньше, и выдает серию исключений «Индекс не существует», одно исключение для каждого столбца. 1005 *

Вот упрощенный пример кода, который демонстрирует проблему: (просто WinForm с DGV и кнопкой.)

    private List<Employee> list;
    private void Form1_Load(object sender, EventArgs e)
    {
        list = new List<Employee>();
        for (int ix = 0; ix < 3; ix++)
        {
            list.Add(ObjectMother.GetEmployee(ix+1));
        }

        dataGridView1.DataSource = list;
    }

    private void cmdDeleteARow_Click(object sender, EventArgs e)
    {
        list.Remove(list[0]);
        dataGridView1.Invalidate();

    }

В ASP.NET при использовании элемента управления GridView есть метод «DataBind ()», который можно вызвать, чтобы заставить его обновить свои данные. Кажется, в WinForms такого нет, или я что-то упустил?

Ответы [ 4 ]

17 голосов
/ 21 сентября 2009

Чтобы DataGridView мог зафиксировать изменения в DataSource, источник должен реализовать IBindingList . List<T> нет, поэтому он не передает свои изменения, а DataGridView не знает, что его нужно обновить.

Простое решение в этом случае - поместить BindingSource между списком и DataGridView, а затем вместо него вызвать Remove():

private List<Employee> list;
private BindingSource bindingSource;
private void Form1_Load(object sender, EventArgs e)
{
    list = new List<Employee>();
    for (int ix = 0; ix < 3; ix++)
    {
        list.Add(ObjectMother.GetEmployee(ix+1));
    }

    dataGridView1.DataSource = bindingSource;
    bindingSource.DataSource = list;
}

private void cmdDeleteARow_Click(object sender, EventArgs e)
{
    bindingSoruce.Remove(list[0]); // or, RemoveAt(0)

    // Probably not necessary:
    // dataGridView1.Invalidate();
}

В качестве альтернативы вы можете использовать BindingList<T> вместо List<T> или создать свой собственный класс списка, который реализует IBindingList.

1 голос
/ 17 сентября 2009

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

Если вы используете отражение, чтобы перейти в свойство DataGridView.DataSource, вы увидите, что методы привязки вызываются только в случае изменения DataSource. Обратите внимание, что изменение содержимого источника данных (например, добавление, изменение или удаление элемента списка) не распознается как изменение источника данных. Чтобы заставить методы привязки данных вызываться, я успешно переназначил DataSource на какой-то другой объект, а затем назначил его обратно в список. Кажется невероятно громоздким и монументальной тратой циклов процессора, но, похоже, работает. Таким образом, код становится:

    private void cmdDeleteARow_Click(object sender, EventArgs e)
    {
        list.Remove(list[0]);
        dataGridView1.DataSource = new List<Employee>();
        dataGridView1.DataSource = list;
        dataGridView1.Invalidate();
    }

Если у кого-то есть идеи получше (и я уверен, что там должны быть какие-то идеи), пожалуйста, дайте мне знать.

0 голосов
/ 08 января 2014

Я пытался использовать метод Validate () объекта-контейнера, и он работает гладко, когда дело доходит до синхронизации представления сетки данных и связанной таблицы данных.

Пример в Visual C ++ может быть представлен как:

// Предполагается, что dgv уже создан в коде как объект Data Grid View

SplitContainer ^ dgvContainer = dynamic_cast (dgv-> Parent-> Parent); dgvContainer -> Validate ();

Надеюсь, это поможет.

0 голосов
/ 17 сентября 2009

Попробуйте

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