.NET Framework 4 - Windows Forms Best Practices for Scaling the Windows Forms DataGridView Control The DataGridView control is designed to provide maximum scalability. If you need to display large amounts of data, you should follow the guidelines described in this topic to avoid consuming large amounts of memory or degrading the responsiveness of the user interface (UI). This topic discusses the following issues: Using cell styles efficiently Using shortcut menus efficiently Using automatic resizing efficiently Using the selected cells, rows, and columns collections efficiently Using shared rows Preventing rows from becoming unshared
If you have special performance needs, you can implement virtual mode and provide your own data management operations. For more information, see Data Display Modes in the Windows Forms DataGridView Control.

Using Cell Styles Efficiently
Each cell, row, and column can have its own style information. Style information is stored in DataGridViewCellStyle objects. Creating cell style objects for many individual DataGridView elements can be inefficient, especially when working with large amounts of data. To avoid a performance impact, use the following guidelines: Avoid setting cell style properties for individual DataGridViewCell or DataGridViewRow objects. This includes the row object specified by the RowTemplate property. Each new row that is cloned from the row template will receive its own copy of the template's cell style object. For maximum scalability, set cell style properties at the DataGridView level. For example, set the DataGridView..::.DefaultCellStyle property rather than the DataGridViewCell..::.Style property. If some cells require formatting other than default formatting, use the same DataGridViewCellStyle instance across groups of cells, rows, or columns. Avoid directly setting properties of type DataGridViewCellStyle on individual cells, rows, and columns. For an example of cell style sharing, see How to: Set Default Cell Styles for the Windows Forms DataGridView Control. You can also avoid a performance penalty when setting cell styles individually by handling the CellFormatting event handler. For an example, see How to: Customize Data Formatting in the Windows Forms DataGridView Control. When determining a cell's style, use the DataGridViewCell..::.InheritedStyle property rather than the DataGridViewCell..::.Style property. Accessing the Style property creates a new instance of the DataGridViewCellStyle class if the property has not already been used. Additionally, this object might not contain the complete style information for the cell if some styles are inherited from the row, column, or control. For more information about cell style inheritance, see Cell Styles in the Windows Forms DataGridView Control.

Using Shortcut Menus Efficiently
Each cell, row, and column can have its own shortcut menu. Shortcut menus in the DataGridView control are represented by ContextMenuStrip controls. Just as with cell style objects, creating shortcut menus for many individual DataGridView elements will negatively impact performance. To avoid this penalty, use the following guidelines: Avoid creating shortcut menus for individual cells and rows. This includes the row template, which is cloned along with its shortcut menu when new rows are added to the control. For maximum scalability, use only the control's ContextMenuStrip property to specify a single shortcut menu for the entire control. If you require multiple shortcut menus for multiple rows or cells, handle the CellContextMenuStripNeeded or RowContextMenuStripNeeded events. These events let you manage the shortcut menu objects yourself, allowing you to tune performance.

Using Automatic Resizing Efficiently
Rows, columns, and headers can be automatically resized as cell content changes so that the entire contents of cells are displayed without clipping. Changing sizing modes can also resize rows, columns, and headers. To determine the correct size, the DataGridView control must examine the value of each cell that it must accommodate. When working with large data sets, this analysis can negatively impact the performance of the control when automatic resizing occurs. To avoid performance penalties, use the following guidelines: Avoid using automatic sizing on a DataGridView control with a large set of rows. If you do use automatic sizing, only resize based on the displayed rows. Use only the displayed rows in virtual mode as well. For maximum scalability, turn off automatic sizing and use programmatic resizing.
For more information, see Sizing Options in the Windows Forms DataGridView Control.

Using the Selected Cells, Rows, and Columns Collections Efficiently
The SelectedCells collection does not perform efficiently with large selections. The SelectedRows and SelectedColumns collections can also be inefficient, although to a lesser degree because there are many fewer rows than cells in a typical DataGridView control, and many fewer columns than rows. To avoid performance penalties when working with these collections, use the following guidelines:

Using Shared Rows
Efficient memory use is achieved in the DataGridView control through shared rows. Rows will share as much information about their appearance and behavior as possible by sharing instances of the DataGridViewRow class. While sharing row instances saves memory, rows can easily become unshared. For example, whenever a user interacts directly with a cell, its row becomes unshared. Because this cannot be avoided, the guidelines in this topic are useful only when working with very large amounts of data and only when users will interact with a relatively small part of the data each time your program is run. A row cannot be shared in an unbound DataGridView control if any of its cells contain values. When the DataGridView control is bound to an external data source or when you implement virtual mode and provide your own data source, the cell values are stored outside the control rather than in cell objects, allowing the rows to be shared. A row object can only be shared if the state of all its cells can be determined from the state of the row and the states of the columns containing the cells. If you change the state of a cell so that it can no longer be deduced from the state of its row and column, the row cannot be shared. For example, a row cannot be shared in any of the following situations: In bound mode or virtual mode, you can provide ToolTips and shortcut menus for individual cells by handling the CellToolTipTextNeeded and CellContextMenuStripNeeded events. The DataGridView control will automatically attempt to use shared rows whenever rows are added to the DataGridViewRowCollection. Use the following guidelines to ensure that rows are shared: To determine whether a row is shared, use the DataGridViewRowCollection..::.SharedRow method to retrieve the row object, and then check the object's Index property. Shared rows always have an Index property value of –1.

Preventing Rows from Becoming Unshared
Shared rows can become unshared as a result of code or user action. To avoid a performance impact, you should avoid causing rows to become unshared. During application development, you can handle the RowUnshared event to determine when rows become unshared. This is useful when debugging row-sharing problems. To prevent rows from becoming unshared, use the following guidelines: Avoid indexing the Rows collection or iterating through it with a foreach loop. You will not typically need to access rows directly. DataGridView methods that operate on rows take row index arguments rather than row instances. Additionally, handlers for row-related events receive event argument objects with row properties that you can use to manipulate rows without causing them to become unshared. If you need to access a row object, use the DataGridViewRowCollection..::.SharedRow method and pass in the row's actual index. Note, however, that modifying a shared row object retrieved through this method will modify all the rows that share this object. The row for new records is not shared with other rows, however, so it will not be affected when you modify any other row. Note also that different rows represented by a shared row may have different shortcut menus. To retrieve the correct shortcut menu from a shared row instance, use the GetContextMenuStrip method and pass in the row's actual index. If you access the shared row's ContextMenuStrip property instead, it will use the shared row index of -1 and will not retrieve the correct shortcut menu. Avoid indexing the DataGridViewRow..::.Cells collection. Accessing a cell directly will cause its parent row to become unshared, instantiating a new DataGridViewRow. Handlers for cell-related events receive event argument objects with cell properties that you can use to manipulate cells without causing rows to become unshared. You can also use the CurrentCellAddress property to retrieve the row and column indexes of the current cell without accessing the cell directly. Avoid cell-based selection modes. These modes cause rows to become unshared. Instead, set the DataGridView..::.SelectionMode property to DataGridViewSelectionMode..::.FullRowSelect or DataGridViewSelectionMode..::.FullColumnSelect. Do not handle the DataGridViewRowCollection..::.CollectionChanged or DataGridView..::.RowStateChanged events. These events cause rows to become unshared. Also, do not call the DataGridViewRowCollection..::.OnCollectionChanged or DataGridView..::.OnRowStateChanged methods, which raise these events. Do not access the DataGridView..::.SelectedCells collection when the DataGridView..::.SelectionMode property value is FullColumnSelect, ColumnHeaderSelect, FullRowSelect, or RowHeaderSelect. This causes all selected rows to become unshared. Do not call the DataGridView..::.AreAllCellsSelected method. This method can cause rows to become unshared. Do not call the DataGridView..::.SelectAll method when the DataGridView..::.SelectionMode property value is CellSelect. This causes all rows to become unshared. Do not set the ReadOnly or Selected property of a cell to false when the corresponding property in its column is set to true. This causes all rows to become unshared. Do not access the DataGridViewRowCollection..::.List property. This causes all rows to become unshared. Do not call the Sort(IComparer) overload of the Sort method. Sorting with a custom comparer causes all rows to become unshared.

See Also
TasksReferenceConceptsOther Resources
|
.NET Framework 4 - Windows Forms Empfohlene Vorgehensweisen für das Skalieren des DataGridView-Steuerelements in Windows Forms Das DataGridView-Steuerelement ist für maximale Skalierbarkeit ausgelegt. Wenn Sie umfangreiche Datenmengen anzeigen müssen, sollten Sie die in diesem Thema beschriebenen Richtlinien befolgen, um zu verhindern, dass der Arbeitsspeicher überlastet oder die Reaktionsfähigkeit der Benutzeroberfläche beeinträchtigt wird. In diesem Thema werden folgende Aspekte behandelt: Effiziente Verwendung von Zellenstilen Effiziente Verwendung von Kontextmenüs Effiziente Verwendung der automatischen Größenanpassung Effiziente Verwendung der Auflistungen für ausgewählte Zellen, Zeilen und Spalten Verwenden freigegebener Zeilen Verhindern, dass die Zeilenfreigabe aufgehoben wird
Bei besonderen Leistungsanforderungen können Sie den virtuellen Modus implementieren und eigene Datenverwaltungsoperationen bereitstellen. Weitere Informationen finden Sie unter Datenanzeigemodi im DataGridView-Steuerelement in Windows Forms.

Effiziente Verwendung von Zellenstilen
Jede Zelle, Zeile und Spalte kann eigene Formatinformationen haben. Formatinformationen werden in DataGridViewCellStyle-Objekten gespeichert. Das Erstellen von Zellenstilobjekten für viele einzelne DataGridView-Elemente kann sich als ineffizient erweisen, besonders bei der Bearbeitung umfangreicher Datenmengen. Befolgen Sie die nachstehenden Richtlinien, um Leistungseinbußen zu vermeiden:

Effiziente Verwendung von Kontextmenüs
Jede Zelle, Zeile und Spalte kann über ein eigenes Kontextmenü verfügen. Kontextmenüs werden im DataGridView-Steuerelement durch ContextMenuStrip-Steuerelemente dargestellt. Genauso wie bei Zellenstilobjekten hat das Erstellen von Kontextmenüs für viele einzelne DataGridView-Elemente negative Auswirkungen auf die Systemleistung. Um diese Leistungsminderung zu vermeiden, beachten Sie die folgenden Richtlinien: Erstellen Sie keine Kontextmenüs für einzelne Zellen und Zeilen. Dies gilt auch für die Zeilenvorlage, die zusammen mit ihrem Kontextmenü geklont wird, sobald dem Steuerelement neue Zeilen hinzugefügt werden. Um optimale Skalierbarkeit zu gewährleisten, verwenden Sie ausschließlich die ContextMenuStrip-Eigenschaft des Steuerelements, um ein einziges Kontextmenü für das gesamte Steuerelement zu erstellen. Wenn Sie mehrere Kontextmenüs für mehrere Zeilen oder Zellen benötigen, behandeln Sie das CellContextMenuStripNeeded-Ereignis oder das RowContextMenuStripNeeded-Ereignis. Diese Ereignisse ermöglichen es Ihnen, die Kontextmenüobjekte selbst zu verwalten und so die Leistung zu optimieren.

Effiziente Verwendung der automatischen Größenanpassung
Die Größe von Zeilen, Spalten und Headern kann in Anpassung an veränderte Zellinhalte automatisch geändert werden, damit der gesamte Inhalt der Zellen sichtbar ist und keine Informationen abgeschnitten werden. Durch das Ändern von Größenanpassungsmodi kann auch die Größe von Zeilen, Spalten und Headern geändert werden. Um die richtige Größe zu bestimmen, muss das DataGridView-Steuerelement den Wert jeder Zelle überprüfen, die es aufnehmen muss. Bei der Arbeit mit umfangreichen Datasets kann sich diese Analyse bei einer automatischen Größenanpassung negativ auf die Steuerelementleistung auswirken. Um Leistungsminderungen zu vermeiden, beachten Sie die folgenden Richtlinien: Verzichten Sie bei einem DataGridView-Steuerelement mit umfangreichen Rowsets auf die automatische Größenanpassung. Wenn Sie die automatische Größenanpassung trotzdem verwenden, führen Sie die Anpassung nur auf der Grundlage der angezeigten Zeilen aus. Auch im virtuellen Modus sollten nur die angezeigten Zeilen verwendet werden. Deaktivieren Sie die automatische Größenanpassung, und verwenden Sie die programmgesteuerte Größenanpassung, um optimale Skalierbarkeit zu erzielen.
Weitere Informationen finden Sie unter Größenänderungsoptionen im DataGridView-Steuerelement in Windows Forms.

Effiziente Verwendung der Auflistungen für ausgewählte Zellen, Zeilen und Spalten
Die SelectedCells-Auflistung bietet bei umfangreichen Auswahlen keine effiziente Leistung. Auch die SelectedRows-Auflistung und die SelectedColumns-Auflistung können sich ineffizient erweisen – wenn auch in einem geringeren Grad. Dies liegt daran, dass ein typisches DataGridView-Steuerelement wesentlich weniger Zeilen als Zellen und wesentlich weniger Spalten als Zeilen enthält. Um Leistungseinbußen bei Verwendung dieser Auflistungen zu vermeiden, beachten Sie die folgenden Richtlinien:

Verwenden freigegebener Zeilen
Eine effiziente Speichernutzung wird im DataGridView-Steuerelement durch freigegebene Zeilen erreicht. Dabei werden von den Zeilen möglichst viele Informationen über Zeilendarstellung und -verhalten gemeinsam genutzt, indem Instanzen der DataGridViewRow-Klasse freigegeben werden. Die gemeinsame Nutzung von Zeileninstanzen entlastet zwar den Arbeitsspeicher, kann aber dazu führen, dass die Freigabe von Zeilen aufgehoben wird. Beispielsweise wird jedes Mal, wenn ein Benutzer direkt mit einer Zelle interagiert, die Freigabe der betreffenden Zeile aufgehoben. Da dieses Verhalten nicht unterbunden werden kann, sind die Richtlinien in diesem Thema nur bei der Arbeit mit sehr großen Datenmengen hilfreich und auch nur dann, wenn Benutzer bei jeder Ausführung des Programms mit einem relativ geringen Teil der Daten interagieren. Eine Zeile kann in einem ungebundenen DataGridView-Steuerelement nicht freigegeben werden, wenn eine ihrer Zellen Werte enthält. Wenn das DataGridView-Steuerelement an eine externe Datenquelle gebunden ist, oder wenn Sie den virtuellen Modus implementieren und eine eigene Datenquelle bereitstellen, werden die Zellwerte außerhalb des Steuerelements und nicht in Zellobjekten gespeichert, wodurch die Zeilen freigegeben werden können. Ein Zeilenobjekt kann nur freigegeben werden, wenn der Zustand all seiner Zellen über den Zustand der Zeile und den jeweiligen Zustand der Spalten ermittelt werden kann, in denen die Zellen enthalten sind. Wenn Sie den Zustand einer Zelle ändern, sodass er nicht mehr vom Zustand der zugehörigen Zeile und Spalte abgeleitet werden kann, kann die Zeile nicht freigegeben werden. Beispielsweise können Zeilen in folgenden Situationen nicht freigegeben werden: Die Zeile enthält eine einzelne ausgewählte Zelle, die sich nicht in einer ausgewählten Spalte befindet. Die Zeile enthält eine Zelle, deren ToolTipText-Eigenschaft oder ContextMenuStrip-Eigenschaft festgelegt ist. Die Zeile enthält DataGridViewComboBoxCell mit festgelegter Items-Eigenschaft.
Im gebundenen oder virtuellen Modus können Sie QuickInfos und Kontextmenüs für einzelne Zellen bereitstellen, indem Sie das CellToolTipTextNeeded-Ereignis und das CellContextMenuStripNeeded-Ereignis behandeln. Das DataGridView-Steuerelement versucht automatisch, freigegebene Zeilen zu verwenden, sobald DataGridViewRowCollection Zeilen hinzugefügt werden. Beachten Sie die folgenden Richtlinien, um sicherzustellen, dass die Zeilenfreigabe erhalten bleibt: Vermeiden Sie es, die Add(Object[])-Überladung der Add-Methode und die Insert(Object[])-Überladung der Insert-Methode aus der DataGridView..::.Rows-Auflistung aufzurufen. Durch diese Überladungen wird die Freigabe von Zeilen automatisch aufgehoben. Stellen Sie sicher, dass die Freigabe der in der DataGridView..::.RowTemplate-Eigenschaft angegebenen Zeile in den folgenden Fällen erhalten bleibt: Achten Sie darauf, dass die Freigabe der durch den indexSource-Parameter angegebenen Zeile erhalten bleibt, wenn die Methoden AddCopy, AddCopies, InsertCopy und InsertCopies der DataGridView..::.Rows-Auflistung aufgerufen werden. Achten Sie darauf, dass die Freigabe der angegebenen Zeile(n) erhalten bleibt, wenn die Add(DataGridViewRow)-Überladung der Add-Methode, die AddRange-Methode, die Insert(Int32,DataGridViewRow)-Überladung der Insert-Methode und die InsertRange-Methode aus der DataGridView..::.Rows-Auflistung aufgerufen werden.
Um festzustellen, ob eine Zeile freigegeben ist, rufen Sie das Zeilenobjekt mit der DataGridViewRowCollection..::.SharedRow-Methode ab und überprüfen dann die Index-Eigenschaft des Objekts. Freigegebene Zeilen verfügen immer über einen Index-Eigenschaftswert von -1.

Verhindern, dass die Zeilenfreigabe aufgehoben wird
Die Freigabe von Zeilen kann durch Code oder aufgrund einer Benutzeraktion aufgehoben werden. Um Auswirkungen auf die Systemleistung zu vermeiden, sollten Sie darauf achten, dass die Freigabe von Zeilen nicht aufgehoben wird. Während der Anwendungsentwicklung können Sie das RowUnshared-Ereignis behandeln, um festzustellen, wann die Freigabe von Zeilen aufgehoben wird. Dies ist beim Debuggen von Problemen bei der Zeilenfreigabe von Nutzen. Um zu verhindern, dass die Freigabe von Zeilen aufgehoben wird, beachten Sie die folgenden Richtlinien: Vermeiden Sie es, die Rows-Auflistung zu indizieren oder sie mit einer foreach-Schleife zu durchlaufen. In aller Regel müssen Sie nicht direkt auf Zeilen zugreifen. DataGridView-Methoden, die für Zeilen verwendet werden, verwenden anstelle von Zeileninstanzen die Argumente für den Zeilenindex. Darüber hinaus empfangen Handler für zeilenbezogene Ereignisse Ereignisargumentobjekte mit Zeileneigenschaften, die Sie zum Bearbeiten von Zeilen verwenden können, ohne dass dabei die Zeilenfreigabe aufgehoben wird. Verwenden Sie die DataGridViewRowCollection..::.SharedRow-Methode, und übergeben Sie den tatsächlichen Index der Zeile, um auf ein Zeilenobjekt zuzugreifen. Beachten Sie jedoch, dass durch das Ändern eines freigegebenen Zeilenobjekts, das über diese Methode abgerufen wird, alle Zeilen geändert werden, die dieses Objekt gemeinsam nutzen. Die Zeile für neue Datensätze wird jedoch nicht mit anderen Zeilen freigegeben, sodass das Ändern anderer Zeilen sich nicht auf diese Zeile auswirkt. Beachten Sie auch, dass verschiedene, durch eine freigegebene Zeile dargestellte Zeilen über unterschiedliche Kontextmenüs verfügen können. Um das korrekte Kontextmenü von der Instanz einer freigegebenen Zeile abzurufen, verwenden Sie die GetContextMenuStrip-Methode und übergeben den tatsächlichen Index der Zeile. Falls Sie stattdessen auf die ContextMenuStrip-Eigenschaft der freigegebenen Zeile zugreifen, wird der Index -1 der freigegebenen Zeile verwendet und das falsche Kontextmenü abgerufen. Vermeiden Sie es, die DataGridViewRow..::.Cells-Auflistung zu indizieren. Durch den direkten Zugriff auf eine Zelle wird die Freigabe der übergeordneten Zeile aufgehoben und eine neue DataGridViewRow instanziiert. Handler für zellenbezogene Ereignisse empfangen Ereignisargumentobjekte mit Zelleigenschaften, die Sie zum Bearbeiten von Zellen verwenden können, ohne dass dabei Zeilenfreigaben aufgehoben werden. Sie können auch mithilfe der CurrentCellAddress-Eigenschaft die Zeilen- und Spaltenindizes der aktuellen Zelle abrufen, ohne direkt auf die Zelle zuzugreifen. Vermeiden Sie zellenbasierte Auswahlmodi. Diese Modi bewirken, dass Zeilenfreigaben aufgehoben werden. Legen Sie stattdessen die DataGridView..::.SelectionMode-Eigenschaft auf DataGridViewSelectionMode..::.FullRowSelect oder DataGridViewSelectionMode..::.FullColumnSelect fest. Das DataGridViewRowCollection..::.CollectionChanged-Ereignis oder das DataGridView..::.RowStateChanged-Ereignis sollte nicht behandelt werden. Diese Ereignisse bewirken, dass Zeilenfreigaben aufgehoben werden. Vermeiden Sie es auch, die DataGridViewRowCollection..::.OnCollectionChanged-Methode oder die DataGridView..::.OnRowStateChanged-Methode aufzurufen, durch die diese Ereignisse ausgelöst werden. Greifen Sie nicht auf die DataGridView..::.SelectedCells-Auflistung zu, wenn der Wert der DataGridView..::.SelectionMode-Eigenschaft FullColumnSelect, ColumnHeaderSelect, FullRowSelect oder RowHeaderSelect lautet. Dadurch wird die Freigabe aller ausgewählten Zeilen aufgehoben. Rufen Sie nicht die DataGridView..::.AreAllCellsSelected-Methode auf. Diese Methode kann bewirken, dass Zeilenfreigaben aufgehoben werden. Vermeiden Sie es, die DataGridView..::.SelectAll-Methode aufzurufen, wenn der Wert der DataGridView..::.SelectionMode-Eigenschaft CellSelect lautet. Dadurch wird die Freigabe aller Zeilen aufgehoben. Legen Sie die ReadOnly-Eigenschaft oder Selected-Eigenschaft einer Zelle nicht auf false fest, wenn die entsprechende Eigenschaft in der zugehörigen Spalte auf true festgelegt ist. Dadurch wird die Freigabe aller Zeilen aufgehoben. Greifen Sie nicht auf die DataGridViewRowCollection..::.List-Eigenschaft zu. Dadurch wird die Freigabe aller Zeilen aufgehoben. Rufen Sie nicht die Sort(IComparer)-Überladung der Sort-Methode auf. Sortierungen mit einem benutzerdefinierten Vergleich führen dazu, dass die Freigabe sämtlicher Zeilen aufgehoben wird.

Siehe auch
AufgabenReferenzKonzepteWeitere Ressourcen
|