Масштабирование элемента управления DataGridView в Windows Forms

Элемент управления DataGridView предназначен для обеспечения максимальной масштабируемости. Если необходимо отображать большие объемы данных, следуйте рекомендациям в этом разделе, чтобы избежать излишнего потребления памяти или снижения скорости реагирования пользовательского интерфейса. В этом разделе обсуждаются следующие вопросы:

  • эффективное использование стилей ячеек;

  • эффективное использование контекстных меню;

  • эффективное использование автоматического изменения размера;

  • эффективное использование коллекций выделенных ячеек, строк и столбцов;

  • использование общих строк;

  • предотвращение совместного использования строк.

Если у вас особые требования к производительности, вы можете реализовать виртуальный режим и предоставить собственные операции управления данными. Дополнительные сведения см. в разделе Режимы отображения данных в элементе управления DataGridView в Windows Forms.

Эффективное использование стилей ячеек

Каждая ячейка, строка или столбец может иметь собственные сведения о стиле. Сведения о стиле хранятся в объектах DataGridViewCellStyle. Создавать объекты стиля ячеек для множества отдельных элементов DataGridView может оказаться неэффективным, особенно при работе с большими объемами данных. Чтобы избежать снижения производительности, следуйте приведенным ниже рекомендациям.

Эффективное использование контекстных меню

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

  • Старайтесь не создавать контекстные меню для отдельных ячеек и строк. Это относится и к шаблону строки, который клонируется вместе с контекстным меню при добавлении новых строк в элемент управления. Для максимальной масштабируемости используйте только свойство ContextMenuStrip элемента управления, чтобы задать единственное контекстное меню для всего элемента управления.

  • Если требуется несколько контекстных меню для разных строк или ячеек, обрабатывайте события CellContextMenuStripNeeded или RowContextMenuStripNeeded. Они позволяют вам самостоятельно управлять объектами контекстного меню, что дает возможность настроить производительность.

Эффективное использование автоматического изменения размера

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

  • Избегайте автоматического определения размера элемента управления DataGridView с большим набором строк. Если оно все же используется, изменяйте размер только на основе отображаемых строк. В виртуальном режиме также используйте только отображаемые строки.

  • Для максимальной масштабируемости отключите автоматическое определение размера и используйте программное изменение размера.

Подробнее см. в статье Варианты изменения размеров элемента управления DataGridView в Windows Forms.

Эффективное использование коллекций выделенных ячеек, строк и столбцов

Коллекция SelectedCells работает неэффективно с большим числом выделенных элементов. Коллекции SelectedRows и SelectedColumns также могут быть неэффективными, хотя и в меньшей степени, так как в типичном элементе управления DataGridView гораздо меньше строк, чем ячеек, и гораздо меньше столбцов, чем строк. Чтобы избежать снижения производительности при работе с этими коллекциями, следуйте приведенным ниже рекомендациям.

Использование общих строк

Общие строки обеспечивают эффективное использование памяти элементом управления DataGridView. Строки будут иметь максимальное количество общих сведений о внешнем виде и поведении благодаря совместному использованию экземпляров класса DataGridViewRow.

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

Строка не может быть общей в несвязанном элементе управления DataGridView, если какие-либо из его ячеек содержат значения. Если элемент управления DataGridView привязан к внешнему источнику данных или если вы реализуете виртуальный режим и предоставляете собственный источник данных, значения ячеек хранятся вне элемента управления, а не в объектах ячеек, что позволяет строкам быть общими.

Объект строки может быть общим, только если состояние всех его ячеек можно определить исходя из состояния строки и состояний столбцов, содержащих ячейки. Если состояние ячейки меняется таким образом, что его больше нельзя вывести из состояния строки и столбца, строка не может быть общей.

Например, строка не может быть общей в любой из следующих ситуаций:

  • Строка содержит одну выделенную ячейку, которая не находится в выделенном столбце.

  • Строка содержит ячейку с заданным свойством ToolTipText или ContextMenuStrip.

  • Строка содержит DataGridViewComboBoxCell с заданным свойством Items.

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

Элемент управления DataGridView автоматически пытается использовать общие строки при каждом добавлении строк в DataGridViewRowCollection. Для обеспечения использования общих строк следуйте приведенным ниже рекомендациям.

  • Избегайте вызова перегрузки Add(Object[]) метода Add и перегрузки Insert(Object[]) метода Insert коллекции DataGridView.Rows. Эти перегрузки автоматически создают строки, не являющиеся общими.

  • Убедитесь в том, что строка, указанная в свойстве DataGridView.RowTemplate, может быть общей в следующих случаях:

    • при вызове перегрузки Add() или Add(Int32) метода Add либо перегрузки Insert(Int32,Int32) метода Insert коллекции DataGridView.Rows;

    • при увеличении значения свойства DataGridView.RowCount;

    • при задании значения свойства DataGridView.DataSource.

  • Убедитесь в том, что строка, заданная параметром indexSource, может быть общей при вызове методов AddCopy, AddCopies, InsertCopy и InsertCopies коллекции DataGridView.Rows.

  • Убедитесь в том, что указанная строка или строки могут быть общими при вызове перегрузки Add(DataGridViewRow) метода Add, метода AddRange, перегрузки Insert(Int32,DataGridViewRow) метода Insert и метода InsertRange коллекции DataGridView.Rows.

Чтобы определить, является ли строка общей, используйте метод DataGridViewRowCollection.SharedRow для получения объекта строки, а затем проверьте свойство Index этого объекта. У общих строк свойство Index всегда имеет значение –1.

Предотвращение совместного использования строк

Общие строки могут перестать быть общими в результате действия кода или пользователя. Чтобы избежать снижения производительности, старайтесь, чтобы строки оставались общими. Во время разработки приложений можно обрабатывать событие RowUnshared, чтобы определять, когда строки перестают быть общими. Это полезно при отладке проблем с совместным использованием строк.

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

  • Избегайте индексирования коллекции Rows или итерации по ней с помощью цикла foreach. Как правило, доступ к строкам напрямую не требуется. Методы DataGridView, работающие со строками, принимают аргументы индекса строки, а не экземпляры строк. Кроме того, обработчики событий, связанных со строками, получают объекты аргументов событий со свойствами строк, которые можно использовать для операций со строками, чтобы они при этом оставались общими.

  • Если необходимо получить доступ к объекту строки, используйте метод DataGridViewRowCollection.SharedRow и передайте фактический индекс строки. Однако обратите внимание, что изменение объекта общей строки, полученного с помощью этого метода, приведет к изменению всех строк, которые совместно используют данный объект. Однако строка для новых записей не используется совместно с другими строками, поэтому изменение любой другой строки на нее не повлияет. Обратите также внимание, что разные строки, представленные общей строкой, могут иметь разные контекстные меню. Чтобы получить правильное контекстное меню из экземпляра общей строки, используйте метод GetContextMenuStrip и передайте фактический индекс строки. Если вы вместо этого обратитесь к свойству ContextMenuStrip общей строки, будет использоваться индекс общей строки –1 и правильное контекстное меню не будет получено.

  • Избегайте индексирования коллекции DataGridViewRow.Cells. Доступ к ячейке напрямую приведет к тому, что ее родительская строка перестанет быть общей и будет создан новый экземпляр DataGridViewRow. Обработчики событий, связанных с ячейками, получают объекты аргументов событий со свойствами ячеек, которые можно использовать для операций с ячейками, чтобы строки при этом оставались общими. Свойство CurrentCellAddress также можно использовать для получения индексов строки и столбца текущей ячейки без доступа к ячейке напрямую.

  • Избегайте режимов выделения на основе ячеек. Эти режимы приводят к тому, что строки перестают быть общими. Вместо этого присвойте свойству DataGridView.SelectionMode значение DataGridViewSelectionMode.FullRowSelect или DataGridViewSelectionMode.FullColumnSelect.

  • Не обрабатывайте события DataGridViewRowCollection.CollectionChanged или DataGridView.RowStateChanged. Эти события приводят к тому, что строки перестают быть общими. Кроме того, не вызывайте методы DataGridViewRowCollection.OnCollectionChanged и DataGridView.OnRowStateChanged, которые создают эти события.

  • Не обращайтесь к коллекции DataGridView.SelectedCells, если свойство DataGridView.SelectionMode имеет значение FullColumnSelect, ColumnHeaderSelect, FullRowSelect или RowHeaderSelect. Это приводит к тому, что все выделенные строки перестают быть общими.

  • Не вызывайте метод DataGridView.AreAllCellsSelected. Он может привести к тому, что строки перестанут быть общими.

  • Не вызывайте метод DataGridView.SelectAll, если свойство DataGridView.SelectionMode имеет значение CellSelect. Это приведет к тому, что все строки перестанут быть общими.

  • Не задавайте для свойства ReadOnly или Selected ячейки значение false, если для соответствующего свойства в ее столбце задано значение true. Это приведет к тому, что все строки перестанут быть общими.

  • Не обращаться к свойству DataGridViewRowCollection.List. Это приведет к тому, что все строки перестанут быть общими.

  • Не вызывайте перегрузку Sort(IComparer) метода Sort. Сортировка с помощью настраиваемой функции сравнения приводит к тому, что все строки перестают быть общими.

См. также