DataGridView virtuellen Modus mit einer einfachen Liste als Quelle
Zuvor fragte ich eine Frage zu meinem dataGridView Leistung aufgrund havign zur Anzeige einer großen Menge von Zeilen, die Hinzugefügt wird, basierend auf einem eingehenden Datenstrom. Mehrere Lösungen wurden gegeben, einer von Ihnen virtuellen Modus aktivieren. MSDN hat einen Artikel über das Thema, aber es fühlt sich komplizierter als das, was ich brauche, wie es verwendet eine Datenbank und ein editierbares Feld. Mein DataGridView ist nur für die Anzeige und die Daten, die ich-display in einer Liste.
Nachdem ich das akzeptiert habe, eine Antwort erhielt ich diesen link: http://www.codeproject.com/Articles/23937/Paging-Data-with-DataGridView-in-VirtualMode . Obwohl, der verwendet eine Datenbank-Beispiel, es ist besser geeignet für das, was ich brauche. Meine Liste enthält die Daten, die ich anzeigen möchten, wie folgt deklariert:
List<ResultRow> captureResults = new List<ResultRow>();
Einen ResultRow Objekt ist wie folgt definiert:
/* Simplified */
public class ResultRow
{
private int first = 0;
private string second = "";
private UInt64 third = 0;
private IPAddress fourth = null;
/* etc */
public ResultRow()
{
}
public void Set (<the values>) //In actuallity a KeyValuePair
{
//field gets set here
}
public UInt64 Third
{
get { return third; }
set { third = value; }
}
/* etc. */
}
Folgenden der oben erwähnte Artikel, ich habe eine ResultRowCache. Das Objekt ist wie folgt vorgenommen:
/* Page size set to 100. */
ResultRowCache _cache = new ResultRowCache(PAGE_SIZE, captureResults);
Auf meinem form Load event mache ich die folgenden (in Bezug auf dieses problem. Ich habe auch einen event-handler zwar, dass das geschieht mit Hilfe der IDE, also nicht direkt zeigt in diesem code. Definition unten!)):
dataGrid.VirtualMode = true;
_cache = new ResultRowCache(PAGE_SIZE, captureResults);
dataGrid.Columns.Add("FirstColumn" , "First column header");
dataGrid.Columns.Add("Second Column", "Second column header");
/* Etc. Adding all columns. (Every member or ResultRow has it's own column. */
dataGrid.RowCount = (int)_cache.TotalCount;
Eine Sache, die ich mich Frage ist, wie die Zeilenanzahl ist initialisiert. Es ist wahrscheinlich, 0 (durch den Konstruktor-Aufruf der ResultRowCache (siehe unten)), aber es scheint nie zu bekommen, wieder geändert. Funktioniert diese Zuordnung, zählen als eine Referenz? Wie funktioniert itupdate selbst?
Trotzdem, weiter mit dem, was ich habe, das ResultRowCache ist wie folgt definiert:
public class ResultRowCache
{
public int PageSize = 100;
public long TotalCount;
public List<ResultRow> CachedData = null;
private List<ResultRow> FullData;
int _lastRowIndex = -1;
public ResultRowCache (int pageSize, List<ResultRow> total)
{
PageSize = pageSize;
FullData = total;
LoadPage( 0 );
}
public void LoadPage (int rowIndex)
{
int lastRowIndex = rowIndex - ( rowIndex % PageSize );
/* Page already loaded */
if( lastRowIndex == _lastRowIndex ) return;
/* New page */
_lastRowIndex = lastRowIndex;
/* Create a new cashes data object */
if( CachedData == null ) CachedData = new List<ResultRow>();
/* If cached data already existed, clear */
CachedData.Clear();
/* The index is valid (there is data */
if (lastRowIndex < FullData.Count)
{
/* Not a full page */
if (lastRowIndex + PageSize > FullData.Count)
{
CachedData = FullData.GetRange(lastRowIndex, ((lastRowIndex + PageSize) - 1) - FullData.Count);
}
/* Full page */
else
{
CachedData = FullData.GetRange(lastRowIndex, PageSize);
}
}
TotalCount = CachedData.Count;
}
}
}
Schließlich, meine CellValueNeeded Ereignis für die datagrid-Komponente ist wie folgt definiert:
void DataGridCellValueNeededEvent(object sender, DataGridViewCellValueEventArgs e)
{
_cache.LoadPage(e.RowIndex);
int rowIndex = e.RowIndex % _cache.PageSize;
switch (dataGrid.Columns[e.ColumnIndex].Name)
{
/* Not actual names, example */
case "FirstColumn": e.Value = _cache.CachedData[rowIndex].First; break;
case "SecondColumn": e.Value = _cache.CachedData[rowIndex].Second; break;
/* Rest of the possibly columns/ResultRow values */
}
}
Problem: Mein datagrid bleibt leer, obwohl die "captureResults" Liste wird gefüllt. Hier ist, was ich bisher ausprobiert:
- Aktualisieren der Zeilenanzahl Mitglied des datagrid-nach dem Wechsel an der Veranstaltung.
- Deklarieren Sie die Liste mit der Summe der Ergebnisse in den cache, um sicherzustellen, es ist immer up to date. (Ich hatte Angst, "außen-Modifikationen" würde nicht gehen Sie durch die Liste, ich ging in die Cache-Konstruktor, obwohl es war ein Hinweis. (Recht neu mit C#))
- Legen Sie die Zeilenanzahl des datagrid-Steuerelements auf 100 (hart-Wert) im load-Ereignis des Formulars.
- Zusätzlich eine "Update ()" - Aufruf an die datagrid-Komponente nach dem hinzufügen von etwas, um das captureResults Liste. (dies geschieht aus einem speziellen Garn, das Berufen ist eine Funktion, die fügt etwas auf der Liste)
Keiner der oben nichts geändert hat. Das Netz bleibt leer. Ich glaube, ich bin etwas fehlt ganz offensichtlich hier. Irgendwelche Vorschläge?
-Bearbeiten - Hinzugefügt, etwas, was ich versuchte, damit es funktioniert.
InformationsquelleAutor Arnold4107176 | 2012-05-09
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich das Gefühl, dass die Verwendung von Cache-erschwert den Prozess ein wenig (obwohl ich fühle die Verantwortung nach senden Ihnen den link zur msdn-one implementiert, die in dieser Art und Weise).
Was ich würde empfehlen, als Ausgangspunkt ist:
Wegwerfen-cache (dies kann später hilfreich sein, wenn Sie laufen in Probleme mit dem Speicher, aber für jetzt können nur Ihre datagrid bevölkern)
Speichern Sie Ihre
List<ResultsRow>
in eine Instanz-variable.Sicherzustellen, dass
dataGrid.VirtualMode = true;
(oder equivilant)Implementieren CellValueNeeded wie folgt:
Hinweis : Sie müssen, setzen einige zusätzlichen öffentlichen Eigenschaften in DataObject, so dass Sie gesetzt werden können, als Werte in der Methode.
Sehen, wie Sie zu erhalten mit. Wenn Sie einige Haltepunkte innerhalb der CellValueNeeded Methode, die helfen sollte, die mit debugging-jede weitere unerwartete Verhalten. Viel Glück.
Wie kommt es, aktualisieren Sie den RowCount-Wert nach jeder Zugabe? Können Sie teilen sich diesen code, da ich nicht sicher bin, wie das funktioniert und klingt nicht ganz richtig. Ordnen Sie Ihre Liste<ResultRow> an eine bindingSource, die dann zugeordnet Raster.DataSource dann rowCounts und internen Listen verfolgt werden soll, ausreichend.
Ah, ich denke, das ist das Ergebnis von meinem Mangel an Verständnis über das Konzept. Ich habe nicht legen Sie eine Datenquelle für mein DataGridView wenn ich aktiviert den virtuellen Modus, wie ich annahm, dies war das performance-problem. Wenn ich halten, die im Takt der einzige Unterschied ist, dass ich den VirtualMode-Eigenschaft auf true, und definiert die CellValueNeeded Veranstaltung. Ist das richtig? Ich verstehe nicht ganz, warum dieser nimmt die Leistung Treffer, die Sie bekommen würden sonst. Ist es die Standardimplementierung des Ereignisses, das ist so ineffizient für große Mengen? Überschreiben Sie es mit den virtuellen Modus off wird wohl nicht klappen, werde ich das gelesen zu haben.
Lief von Zeichen auf meinen letzten post, aber ich wollte noch hinzufügen, dass ich werde versuchen, mein code für die Datenquelle aktiviert und die Zeilenanzahl aktualisieren deaktiviert. Ich lasse Sie wissen, die Ergebnisse! (Kann ich nicht testen diese sofort leider)
Es hängt wirklich, man sollte nicht immer jede Art von Leistung trifft, wenn man es richtig umsetzt. Allerdings.. wenn Sie hatte eine auto-Eigenschaft, die wiederum aufgefüllt Kind einige Eigenschaften der DataRow aus einer Datenbank, die Sie erhalten würden, zu einem Leistungseinbruch. Das ist nur ein Beispiel von vielen, ist Es sehr schwer dir zu helfen ohne zu sehen, den code, would you mind posting ein follow-up?
InformationsquelleAutor Patrick McCurley