Событие CellFormatting в C # действительно медленное - PullRequest
2 голосов
/ 03 января 2012

Я боролся с событием CellFormatting, это так медленно.

У меня есть DataGridView что-то вроде этого:

enter image description here

Я написал функцию, которая срабатывает, когда вы нажимаете флажок в заголовке, и он устанавливает все флажки для проверки в этом столбце ....

private void checkboxHeader_CheckedChanged(object sender, EventArgs e)
    {
        for (int i = 0; i < dataGridView1.RowCount; i++)
        {
            dataGridView1[0, i].Value = ((CheckBox)dataGridView1.Controls.Find("checkboxHeader", true)[0]).Checked;
        }
        //dataGridView1.EndEdit();
    }  

И эта функция работает, когда у меня есть что-то вроде 10 строк, она работает отлично, но когда у меня есть 300 строк, что-то, что у меня должно быть ... есть примерно 9-секундная задержка для установки всех флажков, и я обнаружил, что это связано с событием CellFormating.

Мой код события CellFormating:

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {

            DataGridViewCellStyle _myStyle = new DataGridViewCellStyle();
            int index = gdv_row.FindIndex(p => p.log == (string)dataGridView1.Rows[e.RowIndex].Cells[1].Value);
            if (index != -1 && dataGridView1.Columns[e.ColumnIndex] is DataGridViewTextBoxColumn && e.RowIndex != -1)
            {
                //e.CellStyle = _myStyle;
                _myStyle.Font = gdv_row[index].font;
                _myStyle.BackColor = gdv_row[index].backgroundcolor_color;
                _myStyle.ForeColor = gdv_row[index].foregroundcolor_color;
                dataGridView1.Rows[e.RowIndex].Cells[1].Style = _myStyle;
            }
        }

и я использовал DoubleBuffering для DataGridView . Теперь я понятия не имею, что мне делать с этим событием CellFormatting ...

Ответы [ 2 ]

3 голосов
/ 03 января 2012

Вы уже пробовали SuspendLayout () и ResumeLayout () ?

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

Если вы используете DoubleBuffering Grid, он по-прежнему перерисовывается, что по-прежнему медленно. Но если вы вообще не перерисовываете, когда заполняете Сетка, это должно привести к драматическим изменениям.

Ваша первая функция может выглядеть так:

private void checkboxHeader_CheckedChanged(object sender, EventArgs e)
    {
        dataGridView1.SuspendLayout();

        for (int i = 0; i < dataGridView1.RowCount; i++)
        {
            dataGridView1[0, i].Value = ((CheckBox)dataGridView1.Controls.Find("checkboxHeader", true)[0]).Checked;
        }

        dataGridView1.ResumeLayout();
    }  

[Изменить 1]

Добавлен пример кода.

[Изменить 2] Чтобы свести к минимуму необходимое рисование строк, вместо создания нового объекта DataGridViewCellStyle для каждой строки, попробуйте напрямую установить свойства существующего стиля:

    private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        int index = gdv_row.FindIndex(p => p.log == (string)dataGridView1.Rows[e.RowIndex].Cells[1].Value);
        if (index != -1 && dataGridView1.Columns[e.ColumnIndex] is DataGridViewTextBoxColumn && e.RowIndex != -1)
        {
            dataGridView1.Rows[e.RowIndex].Cells[1].Style.Font = gdv_row[index].font;
            dataGridView1.Rows[e.RowIndex].Cells[1].Style.BackColor = gdv_row[index].backgroundcolor_color;
            dataGridView1.Rows[e.RowIndex].Cells[1].Style.ForeColor = gdv_row[index].foregroundcolor_color;
        }
    }

Наконец, в поисках решения, я нашел этот документ MSDN: Рекомендации по масштабированию элемента управления DataGridView в Windows Forms

[РЕДАКТИРОВАТЬ 3] (Ответ на комментарий Эсана ниже)

Это потому, что «а» - это значение, которое немедленно отображается в таблице, в то время как исходная строка выполняет значительную работу: * Выполняет поиск нужного значения, включая все дочерние элементы управления * Создает массив с найденными результатами * Делает приведение от объекта к CheckBox * Он делает все это для каждой отдельной строки в вашей сетке

Становится очевидным, что это занимает больше времени, чем больше элементов у вас в DataGridView.

Если я правильно понял ваш код, это должно помочь вам изменить метод на следующий:

  CheckBox headerBox = ((CheckBox)dataGridView1.Controls.Find("checkboxHeader", true)[0]);
  for (int i = 0; i < dataGridView1.RowCount; i++)
  {
    dataGridView1[0, i].Value = headerBox.Checked;
  }

Делая это, вы выполняете поиск только один раз.

0 голосов
/ 03 января 2012

Если вы хотите прекратить рисовать элемент управления при проверке всех строк, вам следует взглянуть на класс DrawingControl из этого поста: /295885/kak-priostanovit-risovanie-dlya-elementa-upravleniya-i-ego-dochernih-elementov...

...