Empfohlene Vorgehensweisen für das Skalieren des DataGridView-Steuerelements in Windows Forms

Das Steuerelement DataGridView ist auf maximale Skalierbarkeit ausgelegt. Wenn Sie große Datenmengen anzeigen müssen, beachten Sie die in diesem Thema beschriebenen Leitlinien, um zu vermeiden, dass große Mengen an Arbeitsspeicher beansprucht werden oder sich die Reaktionsfähigkeit der Benutzeroberfläche (UI) verschlechtert. In diesem Thema werden folgende Punkte erörtert:

  • Effizientes Verwenden von Zellenstilen

  • Effizientes Verwenden von Kontextmenüs

  • Effizientes Verwenden der automatischen Größenänderung

  • Effizientes Verwenden der ausgewählten Zellen, Zeilen und Spaltensammlungen

  • Verwenden freigegebener Zeilen

  • Verhindern, dass die Freigabe von Zeilen aufgehoben wird

Bei speziellen Leistungsanforderungen können Sie den virtuellen Modus implementieren und eigene Datenverwaltungsvorgänge bereitstellen. Weitere Informationen finden Sie unter Datenanzeigemodi im DataGridView-Steuerelement von Windows Forms.

Effizientes Verwenden von Zellenstilen

Jede Zelle, Zeile und Spalte kann über eigene Stilinformationen verfügen. Stilinformationen werden in DataGridViewCellStyle-Objekten gespeichert. Das Erstellen von Zellenstilobjekten für viele einzelne DataGridView-Elemente kann ineffizient sein, insbesondere beim Arbeiten mit großen Datenmengen. Um Leistungseinbußen zu vermeiden, sollten Sie die folgenden Leitlinien beachten:

Effizientes Verwenden von Kontextmenüs

Jede Zelle, Zeile und Spalte kann über ein eigenes Kontextmenü verfügen. Kontextmenüs im DataGridView-Steuerelement werden durch ContextMenuStrip-Steuerelemente dargestellt. Genau wie bei Zellenstilobjekten wirkt sich die Erstellung von Kontextmenüs für viele einzelne DataGridView-Elemente negativ auf die Leistung aus. Um diese Einbußen zu vermeiden, befolgen Sie die folgenden Leitlinien:

  • Vermeiden Sie das Erstellen von Kontextmenüs für einzelne Zellen und Zeilen. Dazu gehört auch die Zeilenvorlage, die zusammen mit ihrem Kontextmenü geklont wird, wenn dem Steuerelement neue Zeilen hinzugefügt werden. Verwenden Sie für maximale Skalierbarkeit nur die ContextMenuStrip-Eigenschaft des Steuerelements, um ein einzelnes Kontextmenü für das gesamte Steuerelement anzugeben.

  • Wenn Sie mehrere Kontextmenüs für mehrere Zeilen oder Zellen benötigen, behandeln Sie das Ereignis CellContextMenuStripNeeded oder RowContextMenuStripNeeded. Mit diesen Ereignissen können Sie die Objekte des Kontextmenüs selbst verwalten und so die Leistung optimieren.

Effizientes Verwenden der automatischen Größenänderung

Die Größe von Zeilen, Spalten und Kopfzeilen kann automatisch geändert werden, wenn sich der Zellinhalt ändert, sodass der gesamte Inhalt der Zellen ohne Beschneiden angezeigt wird. Durch Ändern der Dimensionierungsmodi können Sie auch die Größe von Zeilen, Spalten und Überschriften ändern. Um die richtige Größe zu bestimmen, muss das DataGridView-Steuerelement den Wert jeder Zelle untersuchen, die es aufnehmen muss. Beim Arbeiten mit großen Datasets kann sich diese Analyse bei der automatischen Größenänderung negativ auf die Leistung des Steuerelements auswirken. Um Leistungseinbußen zu vermeiden, beachten Sie die folgenden Leitlinien:

Weitere Informationen finden Sie unter Dimensionierungsoptionen im DataGridView-Steuerelement in Windows Forms.

Effizientes Verwenden der ausgewählten Zellen, Zeilen und Spaltensammlungen

Die SelectedCells-Sammlung arbeitet bei großen Auswahlen nicht effizient. Die Sammlungen SelectedRows und SelectedColumns können ebenfalls ineffizient sein, wenn auch in geringerem Maße, da es in einem typischen DataGridView-Steuerelement wesentlich weniger Zeilen als Zellen und wesentlich weniger Spalten als Zeilen gibt. Um Leistungseinbußen beim Arbeiten mit diesen Sammlungen zu vermeiden, beachten Sie die folgenden Leitlinien:

Verwenden freigegebener Zeilen

Eine effiziente Nutzung des Arbeitsspeichers wird im DataGridView-Steuerelement durch freigegebene Zeilen erreicht. Die Zeilen teilen so viele Informationen wie möglich zu ihrem Aussehen und Verhalten, indem Instanzen der DataGridViewRow-Klasse freigegeben werden.

Die Freigabe von Zeileninstanzen spart zwar Arbeitsspeicher, aber es kann leicht passieren, dass die Freigabe von Zeilen aufgehoben wird. Wenn ein Benutzer beispielsweise direkt mit einer Zelle interagiert, wird die Freigabe ihrer Zeile aufgehoben. Da sich dies nicht vermeiden lässt, sind die Anleitungen in diesem Thema nur dann sinnvoll, wenn Sie mit sehr großen Datenmengen arbeiten und wenn die Benutzer bei jeder Ausführung Ihres Programms nur mit einem relativ kleinen Teil der Daten interagieren werden.

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 Sie den virtuellen Modus implementieren und Ihre eigene Datenquelle bereitstellen, werden die Zellwerte außerhalb des Steuerelements und nicht in Zellobjekten gespeichert, sodass die Zeilen freigegeben werden können.

Ein Zeilenobjekt kann nur dann freigegeben werden, wenn der Zustand aller seiner Zellen anhand des Zustands der Zeile und der Zustände der Spalten, die die Zellen enthalten, bestimmt werden kann. Wenn Sie den Zustand einer Zelle so ändern, dass er nicht mehr anhand des Zustands ihrer Zeile und Spalte abgeleitet werden kann, kann die Zeile nicht freigegeben werden.

Eine Zeile kann z. B. in einer der 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, für die die Eigenschaft ToolTipText oder ContextMenuStrip festgelegt wurde.

  • Die Zeile enthält eine DataGridViewComboBoxCell, für die die Items-Eigenschaft festgelegt wurden.

Im gebundenen oder virtuellen Modus können Sie QuickInfos und Kontextmenüs für einzelne Zellen bereitstellen, indem Sie die Ereignisse CellToolTipTextNeeded und CellContextMenuStripNeeded behandeln.

Das DataGridView-Steuerelement versucht automatisch, freigegebene Zeilen zu verwenden, wenn dem DataGridViewRowCollection-Steuerelement Zeilen hinzugefügt werden. Beachten Sie die folgenden Leitlinien, um sicherzustellen, dass Zeilen freigegeben werden:

  • Vermeiden Sie den Aufruf der Add(Object[])-Überladung der Add-Methode und der Insert(Object[])-Überladung der Insert-Methode der DataGridView.Rows-Sammlung. Diese Überladungen erstellen automatisch Zeilen mit aufgehobener Freigabe.

  • Achten Sie darauf, dass die in der DataGridView.RowTemplate-Eigenschaft angegebene Zeile in den folgenden Fällen freigegeben werden kann:

  • Stellen Sie sicher, dass die durch den indexSource-Parameter angegebene Zeile freigegeben werden kann, wenn die Methoden AddCopy, AddCopies, InsertCopy und InsertCopies der DataGridView.Rows-Sammlung aufgerufen werden.

  • Stellen Sie sicher, dass die angegebenen Zeilen freigegeben werden können, wenn Sie die Add(DataGridViewRow)-Überladung der Add-Methode, die AddRange-Methode, die Insert(Int32,DataGridViewRow)-Überladung der Insert-Methode und die InsertRange-Methode der DataGridView.Rows-Sammlung aufrufen.

Um festzustellen, ob eine Zeile freigegeben ist, verwenden Sie die DataGridViewRowCollection.SharedRow-Methode zum Abrufen des Zeilenobjekts, und prüfen dann die Index-Eigenschaft des Objekts. Der Wert der Index-Eigenschaft für freigegebene Zeilen ist stets -1.

Verhindern, dass die Freigabe von Zeilen aufgehoben wird

Die Freigabe von Zeilen kann durch Code oder eine Benutzeraktion aufgehoben werden. Um Leistungseinbußen zu vermeiden, sollten Sie verhindern, dass die Freigabe von Zeilen aufgehoben wird. Während der Anwendungsentwicklung können Sie das RowUnshared-Ereignis behandeln, um festzustellen, wann die Freigabe von Zeilen aufgehoben wird. Dies ist hilfreich beim Debuggen von Zeilenfreigabeproblemen.

Um zu verhindern, dass die Freigabe von Zeilen aufgehoben wird, beachten Sie die folgenden Leitlinien:

  • Vermeiden Sie die Indizierung der Rows-Sammlung oder die Iteration durch eine foreach-Schleife. Sie müssen in der Regel nicht direkt auf Zeilen zugreifen. DataGridView-Methoden, die auf Zeilen angewendet werden, verwenden Zeilenindexargumente und keine Zeileninstanzen. Darüber hinaus erhalten Handler für zeilenbezogene Ereignisse Ereignisargumentobjekte mit Zeileneigenschaften, die Sie verwenden können, um Zeilen zu ändern, ohne dass deren Freigabe aufgehoben wird.

  • Wenn Sie auf ein Zeilenobjekt zugreifen müssen, verwenden Sie die DataGridViewRowCollection.SharedRow-Methode, und geben Sie den tatsächlichen Index der Zeile an. Beachten Sie jedoch, dass die Änderung eines freigegebenen Zeilenobjekts, das über diese Methode abgerufen wird, alle Zeilen ändert, die dieses Objekt freigeben. Die Zeile für neue Datensätze wird jedoch nicht für andere Zeilen freigegeben, sodass sie nicht beeinflusst wird, wenn Sie eine andere Zeile ändern. Beachten Sie auch, dass verschiedene Zeilen, die durch eine freigegebene Zeile dargestellt werden, unterschiedliche Kontextmenüs haben können. Um das richtige Kontextmenü aus einer freigegebenen Zeileninstanz abzurufen, verwenden Sie die GetContextMenuStrip-Methode und geben den tatsächlichen Index der Zeile an. Wenn Sie stattdessen auf die ContextMenuStrip-Eigenschaft der freigegebenen Zeile zugreifen, wird der freigegebene Zeilenindex -1 verwendet, und das richtige Kontextmenü wird nicht abgerufen.

  • Vermeiden Sie die Indizierung der DataGridViewRow.Cells-Sammlung. Der Direktzugriff auf eine Zelle führt dazu, dass die Freigabe der übergeordneten Zeile aufgehoben und eine neue DataGridViewRow instanziiert wird. Handler für zellenbezogene Ereignisse erhalten Ereignisargumentobjekte mit Zelleneigenschaften, die Sie verwenden können, um Zellen zu ändern, ohne dass die Freigabe von Zeilen aufgehoben wird. Sie können auch die CurrentCellAddress-Eigenschaft verwenden, um die Zeilen- und Spaltenindizes der aktuellen Zelle abzurufen, ohne direkt auf die Zelle zuzugreifen.

  • Vermeiden Sie zellenbasierte Auswahlmodi. Diese Modi führen dazu, dass die Freigabe von Zeilen aufgehoben wird. Legen Sie stattdessen die DataGridView.SelectionMode-Eigenschaft auf DataGridViewSelectionMode.FullRowSelect oder DataGridViewSelectionMode.FullColumnSelect fest.

  • Behandeln Sie nicht die Ereignisse DataGridViewRowCollection.CollectionChanged und DataGridView.RowStateChanged. Diese Ereignisse führen dazu, dass die Freigabe von Zeilen aufgehoben wird. Rufen Sie auch nicht die Methoden DataGridViewRowCollection.OnCollectionChanged oder DataGridView.OnRowStateChanged auf, die diese Ereignisse auslösen.

  • Greifen Sie nicht auf die DataGridView.SelectedCells-Sammlung zu, wenn der Wert der DataGridView.SelectionMode-Eigenschaft FullColumnSelect, ColumnHeaderSelect, FullRowSelect, oder RowHeaderSelect ist. Dies bewirkt, dass die Freigabe aller ausgewählten Zeilen aufgehoben wird.

  • Rufen Sie nicht die DataGridView.AreAllCellsSelected-Methode auf. Diese Methode kann dazu führen, dass die Freigabe von Zeilen aufgehoben wird.

  • Rufen Sie nicht die DataGridView.SelectAll-Methode auf, wenn der Wert der DataGridView.SelectionMode-Eigenschaft CellSelect ist. Dies bewirkt, dass die Freigabe aller Zeilen aufgehoben wird.

  • Legen Sie die Eigenschaft ReadOnly oder Selected einer Zelle nicht auf false fest, wenn die entsprechende Eigenschaft in ihrer Spalte auf true festgelegt ist. Dies bewirkt, dass die Freigabe aller Zeilen aufgehoben wird.

  • Greifen Sie nicht auf die DataGridViewRowCollection.List-Eigenschaft zu. Dies bewirkt, dass die Freigabe aller Zeilen aufgehoben wird.

  • Rufen Sie nicht die Sort(IComparer)-Überladung der Sort-Methode auf. Das Sortieren mit einer benutzerdefinierten Vergleichsfunktion führt dazu, dass die Freigabe aller Zeilen aufgehoben wird.

Weitere Informationen