DataGridView的虚拟模式用一个简单的列表作为源(DataGridView virtual

2019-06-24 06:43发布

以前我问了一下我的dataGridView的性能问题,由于它havign显示大量的是那些获得基于进入流添加的行的。 多种解决方案给予,其中一个支持虚拟模式。 MSDN有关于这个问题的文章,但它感觉比我所需要的,因为它使用一个数据库和一个编辑字段更加复杂。 我的DataGridView只显示我显示的数据被放置在列表中。

我接受的答案后,我收到此链接: http://www.codeproject.com/Articles/23937/Paging-Data-with-DataGridView-in-VirtualMode 。 即使是使用数据库的例子,它是更适合我的需要。 我的列表将包含我想要显示如下声明中的数据:

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

甲ResultRow对象被定义如下:

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

}

按照上面提到的文章中,我创建了一个ResultRowCache。 该目的是制备如下:

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

在我的窗体的Load事件中,我做了以下(与此相关的问题,我还添加了一个事件处理程序虽然这是一个使用IDE,无法直接显示在此代码做如下定义。!)):

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;

有一两件事我想知道是怎样的行数在这里初始化。 这也可能是0(由于ResultRowCache的构造函数调用(见下文)),但它似乎从来就没再改变。 这是否算分配作为参考? 如何itupdate本身?

无论如何,以后与我有什么,该ResultRowCache定义如下:

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

最后,我为DataGrid CellValueNeeded事件被定义如下:

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

问题:我的DataGrid中保持为空即使“captureResults”列表中得到填补。 这是我试过到目前为止:

  • 更新DataGrid的行数成员在事件中的开关之后。
  • 声明与高速缓存内的结果总量的名单,以确保它总是最新的。 (我害怕“外修改”不会经历到我,即使它是一个参考缓存的构造函数传递的列表。(用C#相当新))
  • 将DataGrid的100在窗体的Load事件的行数(硬值)。
  • 添加一些东西到captureResults列表后增加了“更新()”调用数据网格。 (这种情况从一个特殊的线程调用它的是增加了一些到列表中的函数)

以上都不改变任何东西。 网格保持为空。 我想我失去了一些东西很明显这里。 有什么建议?

CNC中添加的东西我试图使它发挥作用。

Answer 1:

我觉得用缓存的过程有点复杂(虽然我觉得发你链接到MSDN其中一个以这种方式实现后负责)。

我会建议作为出发点是:

  1. 扔掉缓存(如果你遇到内存问题,这可能是有用的过去了,但是现在,让我们找你的数据网格填充)

  2. 存储您的List<ResultsRow>在一个实例变量。

  3. 确保dataGrid.VirtualMode = true; (或equivilant)

  4. 实施CellValueNeeded如下:

      private void gridContacts_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) { ResultRow dataObject = resultRows[e.RowIndex]; switch(e.ColumnIndex) { case 0: e.Value = dataObject.First; break; case 1 : e.Value = dataObject.Second; break; //etc.. } } 

注意:您需要在数据对象暴露了一些额外的公共属性,使它们可以被设置为在法价值。

看你怎么得到这一点。 如果设置了CellValueNeeded方法应与调试任何进一步的异常行为帮内一些断点。 祝好运。



文章来源: DataGridView virtual mode with a simple list as a source