DataGrid медленно перерисовывает

Я использую System.Windows.Forms.DataGrid. Он заполнен примерно 3000 строками и очень медленно перерисовывается. Если я минимизирую и максимизирую свою форму, все остальные элементы управления просто отображаются, но в конечном итоге я наблюдаю, как перерисовка DataGrid строка за строкой. Все в этом DataGrid доступно только для чтения, если это имеет значение.

Обновление:

Я не совсем уверен, как правильно реализовать событие CellValueNeeded () для моего проекта, и поможет ли это повысить производительность DataGrid в моем случае.

Я создаю пользовательский элемент управления, содержащий DataGridView (см. Код ниже). Когда вызывается метод SetProject (), мой элемент управления устанавливается на конкретный экземпляр моего класса Project. Затем элемент управления использует статический метод Informa.Data.GetProjectDataTable (Project proj) для извлечения DataTable из проекта. Затем для свойства DataSource объекта DataGrid устанавливается значение возвращаемого DataTable.

Я впервые сделал что-нибудь с ADO или DataGrids, так что терпите меня. Похоже, CellValueNeed () позволяет мне переопределить то, как DataGrid находит значение для одной из своих ячеек, но в моем случае это намного сложнее, чем примеры в MSDN. Фактический источник моих данных - это древовидная структура различных объектов Node, корнем которой является экземпляр проекта. Каждый узел может иметь переменный набор свойств, который также может быть расширен пользователем во время выполнения. Затем существует множество других сложностей с узлами, наследующими значения свойств от своих родительских узлов и суммирующими другие свойства от своих дочерних узлов.

Informa.Data.GetProjectDataTable () преодолевает все это безумие и генерирует единую плоскую DataTable со всеми свойствами всех узлов. На данный момент меня не волнует возможность связать любое изменение этой таблицы с исходной древовидной структурой или обновлять определенные части таблицы при изменении древовидной структуры. Все, что я хочу сделать, это отобразить данные пользователю в DataGrid.

Итак, могу ли я реализовать CellValueNeeded () для чтения из DataTable, предоставленного проектом? Я бы подумал, что DataGrid уже знает, как эффективно использовать DataTable в качестве DataSource?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Informa;

namespace Informa
{
public partial class ProjectGridControl : UserControl
{
    private Project proj;

    public ProjectGridControl()
    {
        InitializeComponent();
    }

    public void SetProject(Project proj)
    {
        this.proj = proj;
        UpdateGridControl();
    }

    public void UpdateGridControl()
    {
        if (this.proj == null)
        {
            this.dataGrid.DataSource = null;
        }
        else
        {
            //Extracts a DataTable from the project and sets it as the 
            //DataSource of the property grid
            this.dataGrid.DataSource = Informa.Data.GetProjectDataTable(proj);
        }
    }
}

}


person Eric Anastas    schedule 09.05.2009    source источник
comment
предлагаю выложить какой-нибудь (урезанный) код ...   -  person Mitch Wheat    schedule 09.05.2009
comment
Какие события зажигают? С какими событиями вы работаете? Если у вас есть код, работающий в каждом столбце / строке / ячейке, который связывается, я бы проверил там.   -  person John B    schedule 09.05.2009
comment
Я не занимаюсь никакими событиями. Я создаю DataTable и устанавливаю его как DataSource для DataGrid. Вот и все.   -  person Eric Anastas    schedule 09.05.2009


Ответы (5)


Жил-был маленький Волк по имени МакроСофт, который провел некоторое время с Овечкой Видией. Они сделали самый медленный рендеринг текста и сетки на планете и переложили всю работу на центральный процессор в год бума развития оборудования; все это время Овца старалась замедлить его еще больше.

Если я прав, вы должны письмом жребию :-)

Вы используете карту NVidia и ее дрянные драйверы или аналогичные, а также видите, что MSFT отказывается исправлять GDI + для аппаратного ускорения вместе с дружественными поставщиками (даже Mono сделает это, прежде чем они решат дать вам некоторую экономию энергии и правильное повторное использование оборудования; вы знаю приличную инженерию).

Оберните свой DataGridView в новый тип (например, наследовать) и установите для его свойства DoubleBuffered значение true, измените код конструктора, чтобы использовать этот новый тип.

Видимый рендеринг «построчно» - вот насколько плоха эта отрасль в 2009-2010 годах с суперкомпьютерами на настольных компьютерах и единственной DLL, которую крупная компания отказывается исправлять, но с радостью взимает плату за то, что она работает еще медленнее на Mounta-Dismounta-Vista. Джокеры ..

person rama-jka toti    schedule 09.05.2009
comment
Да, установка двойной буферизации на true, похоже, исправила это. Спасибо. - person Eric Anastas; 11.05.2009
comment
класс DBDataGridView: System.Windows.Forms.DataGridView {общедоступный DBDataGridView () {DoubleBuffered = true; }} - person Zsolti; 17.06.2011
comment
Я заполняю Datagridview с помощью bindingsource. У меня около 1000 записей. Я использовал свойство DoubleBuffered и установил его значение true. Я все еще получаю это очень медленно. - person Vijay Balkawade; 19.04.2012

У вас включено автоматическое изменение размера столбцов? У меня были пользователи, которые сильно замедляли работу нашего приложения всего с 10 строками, потому что было включено автоматическое изменение размера. По сути, одна сетка позволяла пользователю устанавливать / снимать флажок, чтобы добавить строку в другую сетку, а вторая сетка будет испытывать экспоненциальное замедление с каждой добавленной строкой.

После некоторого профилирования я обнаружил, что на добавление 5 строк во вторую таблицу уходит ~ 12 секунд. Наконец, попытался отключить автоматическое изменение размера столбцов, и теперь это происходит мгновенно.

person Chris Doggett    schedule 09.05.2009
comment
Автоматическое изменение размеров строк и столбцов отключено. Спасибо за предложение. - person Eric Anastas; 11.05.2009
comment
@Chris Doggett: СПАСИБО, СПАСИБО, СПАСИБО !!! После 1,5 часов отладки, наконец, нашел ваш пост. И теперь выбор строки выполняется примерно на 500% быстрее ;-) - person andzep; 20.06.2011
comment
Привет. могу я узнать, как выключить AutoSize? не могу найти по нему никакой документации. благодаря. - person Yisroel M. Olewski; 14.02.2012
comment
Блестящее наблюдение! Забавно, что это имеет такое значение. - person poy; 20.07.2012

У меня были большие проблемы с медленной отрисовкой datagridview. Мне нужно было, чтобы мой был как можно больше на экране, и казалось, что его физический размер гораздо больше влияет на скорость боли, чем объем данных и т. Д. Что действительно помогло мне, так это установить CellBorderStyle = None (очевидно, каждая ячейка отвечает за рисование своей собственной границы, что кажется смешным, поскольку границы ячеек остаются фиксированными на экране, поэтому не должно быть необходимости для каждой ячейки постоянно перерисовывать свои собственные границы при прокрутке, но в любом случае ...).

Сетка без границ ячеек на самом деле не очень хорошая сетка. Но, к счастью, вы можете установить DividerWidth как для столбцов, так и для строк. По умолчанию эти значения равны 0, но установка их на 1 (или выше, если вы хотите толще) вернет вам границы «ячеек», идентичные по внешнему виду CellBorderStyle = Single, но на этот раз окрашенные «статически» (из-за отсутствия лучшего слова ) для всего представления данных.

Кроме того, установите для свойств AutoResize значение False, если у вас много строк.

Улучшение скорости рисования было ОГРОМНЫМ, по крайней мере, в моем случае.

person Nick    schedule 04.02.2011
comment
Замечательное наблюдение! У меня включен виртуальный режим, и ничего не помогло (у меня сетка 20x7, 3 обновления за 20 мс по таймеру). Но этот резко улучшил производительность. - person Alex; 30.08.2012
comment
Вам понадобилось это решение, если вы пробовали решение с двойной буферизацией? - person Dan W; 10.09.2012

DataGridView должен без проблем обрабатывать 3000 строк в виртуальном режиме.

Обязательно установите для VirtualMode значение true (вы упомянули, что пробовали это), а также реализуйте CellValueNeeded правильно.

Подробнее читайте в пошаговом руководстве MSDN в VirtualMode.

person Reed Copsey    schedule 09.05.2009

В Visual Studio 2015, когда для 2 столбцов DataGridView AutoSize установлено значение Нет, но

dgv1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders;

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

Так что, если я REM вычеркну вышеприведенную строку, пользовательский интерфейс теперь работает быстро. См. _3 _ и, предположительно, та же проблема с _ 4_

person Drew    schedule 17.10.2016