Масштабирование элемента управления DataGridView в Windows Forms
Обновлен: Ноябрь 2007
Элемент управления DataGridView позволяет обеспечить максимальную масштабируемость. При необходимости отображения больших объемов данных следует придерживаться рекомендаций, приведенных в данном разделе, во избежание избыточного потребления памяти или замедления работы пользовательского интерфейса. В этом разделе обсуждаются следующие вопросы:
эффективное использование стилей ячеек;
эффективное использование контекстных меню;
эффективное использование автоматического изменения размеров;
эффективное использование коллекций выбранных ячеек, строк и столбцов;
использование общих строк;
предотвращение блокирования общего доступа к строкам.
Если предъявляются особые требования к производительности, можно реализовать виртуальный режим и обеспечить выполнение особых операций по управлению данными. Дополнительные сведения см. в разделе Режимы отображения данных в элементе управления DataGridView в Windows Forms.
Эффективное использование стилей ячеек
Каждая ячейка, строка и столбец может иметь сведения о стиле. Сведения о стиле хранятся в объектах DataGridViewCellStyle. Создание объектов стиля ячеек для большого числа элементов DataGridView может оказаться неэффективным, особенно при работе с большими объемами данных. Чтобы избежать снижения производительности, воспользуйтесь следующими рекомендациями.
Избегайте задания стиля ячеек для каждого отдельного объекта DataGridViewCell или DataGridViewRow. Это относится и к объектам строки, определяемым свойством RowTemplate. Объект стиля ячеек, связанный с шаблоном строк, будет копироваться для каждой новой строки, создаваемой на основе шаблона. Для обеспечения максимальной масштабируемости следует задавать свойства стиля ячеек на уровне DataGridView. Так, задание свойства DataGridView.DefaultCellStyle следует предпочесть заданию свойства DataGridViewCell.Style.
Если для некоторых ячеек требуется форматирование, отличное от форматирования по умолчанию, используйте один экземпляр DataGridViewCellStyle для групп ячеек, строк или столбцов. Избегайте прямого задания свойств типа DataGridViewCellStyle для отдельных ячеек, строк и столбцов. Пример совместного использования стиля ячеек см. в разделе Практическое руководство. Установка стилей ячейки по умолчанию для элемента управления DataGridView в Windows Forms. Избежать потери производительности, связанной с заданием стиля ячеек по отдельности, можно путем обработки события CellFormatting. Пример см. в разделе Практическое руководство. Настройка форматирования данных элемента управления DataGridView в Windows Forms.
При определении стиля ячейки свойство DataGridViewCell.InheritedStyle следует предпочесть свойству DataGridViewCell.Style. Если свойство Style ранее не использовалось, то при обращении к нему создается новый экземпляр класса DataGridViewCellStyle. Кроме того, сведения о стиле ячейки, содержащиеся в этом объекте, могут быть неполными, если некоторые стили наследуются от строк, столбцов или элементов управления. Дополнительные сведения о наследовании стилей ячеек см. в разделе Стили ячеек элемента управления DataGridView в Windows Forms.
Эффективное использование контекстных меню
Каждая ячейка, строка и столбец может иметь собственное контекстное меню. Контекстные меню в элементе управления DataGridView представлены элементами управления ContextMenuStrip. Так же как и в случае с объектами стиля ячеек, создание контекстных меню для множества отдельных элементов DataGridView может отрицательно сказаться на производительности. Чтобы избежать потерь производительности, воспользуйтесь следующими рекомендациями.
Избегайте создания контекстных меню для отдельных ячеек или строк. Это относится и к шаблону строк, который копируется вместе с контекстным меню при добавлении в элемент управления новых строк. Для обеспечения максимальной масштабируемости используйте только свойство ContextMenuStrip элемента управления, чтобы определить для него единое контекстное меню.
Если необходимо создать несколько контекстных меню для разных строк или ячеек, прибегните к обработке событий CellContextMenuStripNeeded или RowContextMenuStripNeeded. Эти события позволяют управлять объектами контекстного меню самостоятельно, производя соответствующую настройку производительности.
Эффективное использование автоматического изменения размеров
Размеры строк, столбцов и заголовков могут изменяться автоматически при изменении содержимого ячеек так, чтобы значения ячеек могли отображаться в них без усечения. Изменение размеров строк, столбцов и заголовков может также осуществляться за счет изменения режимов изменения размеров. Для правильного определения размеров элемент управления DataGridView должен проверить значение каждой содержащейся в нем ячейки. При работе с большими объемами данных эта проверка может отрицательно сказаться на производительности элемента управления при выполнении автоматического изменения размеров. Чтобы избежать потерь производительности, воспользуйтесь следующими рекомендациями.
Избегайте использования автоматического изменения размеров, если элемент DataGridView содержит большое количество строк. Если автоматическое изменение размеров все же используется, применяйте его только к отображаемым строкам. Виртуальный режим также следует применять только к отображаемым строкам.
Для строк и столбцов используйте поле DisplayedCells или DisplayedCellsExceptHeaders перечислений DataGridViewAutoSizeRowsMode, DataGridViewAutoSizeColumnsMode и DataGridViewAutoSizeColumnMode.
Для заголовков строк используйте поле AutoSizeToDisplayedHeaders или AutoSizeToFirstHeader перечисления DataGridViewRowHeadersWidthSizeMode.
Для обеспечения максимальной масштабируемости отключите автоматическое изменение размеров и воспользуйтесь программным изменением размеров.
Дополнительные сведения см. в разделе Изменение размеров управления DataGridView в Windows Forms.
Эффективное использование коллекций выбранных ячеек, строк и столбцов
Коллекция SelectedCells обладает низкой эффективностью при выделении большого числа ячеек. Коллекции SelectedRows и SelectedColumns также могут оказаться неэффективными, хотя и в меньшей степени, поскольку обычно элемент управления DataGridView имеет гораздо меньше строк, чем ячеек, и гораздо меньше столбцов, чем строк. Чтобы избежать потерь производительности при работе с этими коллекциями, воспользуйтесь следующими рекомендациями.
Чтобы определить, были ли выделены все ячейки элемента управления DataGridView, перед тем как получить доступ к содержимому коллекции SelectedCells, необходимо проверить значение, возвращаемое методом AreAllCellsSelected. Следует обратить внимание, однако, что этот метод может заблокировать общий доступ к строкам. Дополнительные сведения см. в следующем разделе.
Избегайте использования свойства Count коллекции System.Windows.Forms.DataGridViewSelectedCellCollection для определения числа выделенных ячеек. Вместо этого воспользуйтесь методом DataGridView.GetCellCount, которому следует передать значение свойства DataGridViewElementStates.Selected. Аналогичным образом, для определения числа выделенных элементов следует воспользоваться методами DataGridViewRowCollection.GetRowCount и DataGridViewColumnCollection.GetColumnCount вместо обращения к коллекциям выделенных строк и столбцов.
Избегайте использования режимов выделения на уровне ячеек. Вместо этого установите свойство DataGridView.SelectionMode равным DataGridViewSelectionMode.FullRowSelect или DataGridViewSelectionMode.FullColumnSelect.
Использование общих строк
Применение общих строк в элементе управления DataGridView позволяет добиться эффективного использования памяти. За счет совместного использования экземпляров класса DataGridViewRow строки будут иметь максимальное количество общих сведений о внешнем виде и поведении.
Совместное использование экземпляров строк позволяет экономить память, однако общий доступ к строкам зачастую блокируется. Например, при прямом взаимодействии пользователя с ячейкой, общий доступ к соответствующей строке блокируется. Поскольку избежать этого невозможно, рекомендации, приводимые в данном разделе, целесообразно использовать только при работе с очень большими объемами данных, и только если пользователи взаимодействуют только с относительно небольшой долей данных при каждом запуске приложения.
Если какие-либо ячейки несвязанного элемента управления DataGridView содержат значения, строку невозможно сделать общей. При привязке элемента управления DataGridView к к внешнему источнику данных или предоставлении собственного источника данных путем реализации виртуального режима значения ячеек хранятся не в объектах ячеек, а вне элемента управления, что позволяет обеспечить совместное использование строк.
Совместное использование объекта строки допустимо допустимо только в том случае, если состояние всех его ячеек можно определить на основании состояния строки и состояний столбцов, к которым относятся ячейки. Если после изменения состояния ячейки, оно не может быть определено, исходя из состояния соответствующей строки и столбца, совместное использование строки невозможно.
Так, строка не может являться общей в следующих ситуациях.
Строка содержит единственную выделенную ячейку, не входящую в выделенный столбец.
Строка содержит ячейку с заданными свойствами ToolTipText или ContextMenuStrip.
Строка содержит DataGridViewComboBoxCell с заданными свойством Items.
В связанном или виртуальном режимах элементы ToolTips или контекстные меню для отдельных ячеек можно обеспечить путем обработки событий CellToolTipTextNeeded и CellContextMenuStripNeeded.
При добавлении строк в коллекцию DataGridViewRowCollection элемент управления DataGridView будет автоматически пытаться использовать общие строки. Чтобы обеспечить совместное использование строк, воспользуйтесь следующими рекомендациями.
Избегайте вызовов перегрузки 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. При использовании пользовательской функции сравнения будет заблокирован общий доступ ко всем выделенным строкам.
См. также
Задачи
Основные понятия
Виртуальный режим элемента управления DataGridView в Windows Forms
Режимы отображения данных в элементе управления DataGridView в Windows Forms
Стили ячеек элемента управления DataGridView в Windows Forms
Изменение размеров управления DataGridView в Windows Forms
Ссылки
Другие ресурсы
Оптимизация производительности элемента управления DataGridView в Windows Forms