Virtueller DataGridView-Modus mit einer einfachen Liste als Quelle

Zuvor stellte ich eine Frage zur Leistung von dataGridView, da eine große Anzahl von Zeilen angezeigt werden musste, die basierend auf einem eingehenden Stream hinzugefügt wurden. Es wurden mehrere Lösungen angegeben, von denen eine den virtuellen Modus aktiviert. MSDN hat einen Artikel zu diesem Thema, der sich jedoch komplizierter anfühlt als das, was ich benötige, da er eine Datenbank und ein bearbeitbares Feld verwendet. Mein DataGridView dient nur zur Anzeige und die von mir angezeigten Daten werden in einer Liste abgelegt.

Nachdem ich eine Antwort akzeptiert hatte, erhielt ich diesen Link:http://www.codeproject.com/Articles/23937/Paging-Data-with-DataGridView-in-VirtualMode . Obwohl hier ein Datenbankbeispiel verwendet wird, ist es besser für das geeignet, was ich brauche. Meine Liste, die die Daten enthält, die ich anzeigen möchte, wird wie folgt deklariert:

<code>List<ResultRow> captureResults = new List<ResultRow>();
</code>

Ein ResultRow-Objekt ist wie folgt definiert:

<code>/* 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. */
</code>

}

Nach dem oben erwähnten Artikel habe ich einen ResultRowCache erstellt. Das Objekt wird wie folgt erstellt:

<code>/* Page size set to 100. */
ResultRowCache _cache   = new ResultRowCache(PAGE_SIZE, captureResults);
</code>

In meinem Formular Lade Ereignis führe ich Folgendes aus (im Zusammenhang mit diesem Problem. Ich habe auch eine Ereignisbehandlungsroutine hinzugefügt, obwohl dies mit der IDE durchgeführt wurde und in diesem Code nicht direkt angezeigt wird. Definition unten!)):

<code>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;
</code>

Ich frage mich, wie der RowCount hier initialisiert wird. Es ist wahrscheinlich 0 (aufgrund des Konstruktoraufrufs von ResultRowCache (siehe unten)), aber es scheint nie wieder geändert zu werden. Zählt diese Zuordnung als Referenz? Wie aktualisiert es sich?

Wie auch immer, ab dem, was ich habe, ist der ResultRowCache wie folgt definiert:

<code>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;
    }
    }
}
</code>

Zuletzt ist mein CellValueNeeded-Ereignis für das Datagrid wie folgt definiert:

<code>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 */
    }
}
</code>

Das Problem: Mein Datagrid bleibt leer, obwohl die Liste "captureResults" gefüllt wird. Folgendes habe ich bisher versucht:

Aktualisieren Sie das RowCount-Member des Datagrids nach dem Wechsel im Ereignis.Deklarieren Sie die Liste mit der Gesamtzahl der Ergebnisse im Cache, um sicherzustellen, dass sie immer auf dem neuesten Stand ist. (Ich befürchtete, dass "äußere Änderungen" nicht zu der Liste führen würden, die ich im zwischengespeicherten Konstruktor übergeben habe, obwohl es sich um eine Referenz handelte. (Ziemlich neu mit C #))Setzen Sie den RowCount des Datagrids im Ladeereignis des Formulars auf 100 (fester Wert).Dem Datagrid wurde ein "Update ()" - Aufruf hinzugefügt, nachdem der Liste "captureResults" etwas hinzugefügt wurde. (Dies geschieht aus einem speziellen Thread, der eine Funktion aufruft, die der Liste etwas hinzufügt.)

Nichts von alledem hat etwas geändert. Das Gitter bleibt leer. Ich glaube, hier fehlt mir etwas ganz Offensichtliches. Irgendwelche Vorschläge?

-edit- Ich habe etwas hinzugefügt, damit es funktioniert.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage