DataGridView虚拟模式,以简单的列表作为源 [英] DataGridView virtual mode with a simple list as a source

查看:115
本文介绍了DataGridView虚拟模式,以简单的列表作为源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以前,我问了一个关于我的dataGridView性能的问题,因为它隐藏了显示大量根据传入流添加的行。给出了多种解决方案,其中之一是启用虚拟模式。 MSDN有一篇关于这个问题的文章,但它比使用数据库和可编辑字段所需要的更复杂。我的DataGridView仅用于显示,我显示的数据被放置在列表中。

Previously I asked a question about my dataGridView's performance due to it havign to display a large amount of rows that get added based on an incoming stream. Multiple solutions were given, one of them enabling virtual mode. MSDN has an article on the subject but it feels more complicated than what I need as it uses a database and an editable field. My DataGridView is only for displaying and the data I display is placed in a List.

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

After I accepted an answer I received this link: http://www.codeproject.com/Articles/23937/Paging-Data-with-DataGridView-in-VirtualMode . Even though that uses a database example, it's better suited for what I need. My List that will contain the data I want to display is declared as follows:

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

ResultRow对象定义如下:

A ResultRow object is defined as follows:

/* 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。对象如下:

Following the article mentioned above, i created a ResultRowCache. The object is made as follows:

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

在我的表单上加载事件我做以下(与此问题相关)我还添加了一个事件处理程序虽然这是使用IDE完成的,因此不能直接显示在此代码中。)):

On my form Load event I do the following (related to this problem. I also added an event handler although that's done using the IDE so not directly showing in this code. Definition below!)):

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;

有一件事我想知道RowCount是如何在这里初始化的,它可能是0(由于ResultRowCache的构造函数调用(见下文)),但是它似乎再也没有被改变分配计数作为参考?如何更新自己?

One thing I am wondering is how the RowCount is initialized here. It's probably 0 (due to the constructor call of ResultRowCache (see below)) but it never seems to get changed again. Does this assignment count as a reference? How does itupdate itself?

无论如何,随着我拥有,ResultRowCache定义如下:

Anyway, onward with what I have, the ResultRowCache is defined as follows:

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事件定义如下:

Lastly, my CellValueNeeded event for the datagrid is defined as follows:

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

问题:即使captureResults列表被填充,我的数据网格保持为空。这是我到目前为止所尝试的:

The problem: My datagrid remains empty even though the "captureResults" list gets filled. Here's what I tried so far:


  • 在事件切换后更新数据网格的RowCount成员。

  • 在缓存中声明具有总结果总数的列表,以确保它始终是最新的。 (我很害怕外部修改)不会通过我在缓存的构造函数中传递的列表,即使它是一个参考(C#相当新))

  • 设置RowCount的数据网格在表单的加载事件中为100(硬值)。

  • 向captureResults列表添加内容后,向datagrid添加了一个Update()调用。 (这发生在一个特殊的线程Invoke的功能,添加一些东西到列表)

  • Update the RowCount member of the datagrid after the switch in the event.
  • Declare the list with the total amount of results within the cache to ensure it's always up to date. (I was afraid "outside modifications" wouldn't go through to the List i passed in the cached constructor even though it was a reference. (Fairly new with C#))
  • Set the RowCount of the datagrid to 100 (hard value) in the form's load event.
  • Added an "Update()" call to the datagrid after adding something to the captureResults list. (this happens from a special thread which Invoke's a function that adds something to the list)

上面没有更改任何东西。网格保持为空。我想我在这里遗漏了一些很明显的东西。任何建议?

None of the above changed anything. The grid remains empty. I think I am missing something quite obvious here. Any suggestions?

-edit-添加了一些我试图让它工作的东西。

-edit- Added something I tried to make it work.

推荐答案

我觉得Cache的使用在某种程度上使程序复杂化(尽管我在发送链接到msdn以这种方式实现的)。

I feel that the use of Cache is complicating the process somewhat (although I do feel responsible after sending you the link to the msdn one which implements in this fashion).

我建议作为起点是:


  1. 丢弃缓存(如果遇到内存问题,这可能会有用),但现在可以让您的数据网格填充)

  1. Throw away the cache (this may be useful later if you run into memory problems, but for now lets just get your datagrid populating)

列表< ResultsRow> 存储在实例变量中。

确保 dataGrid.VirtualMode = true; (或等同)

实现CellValueNeeded如下:

Implement CellValueNeeded as follows:

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


注意:您将需要在DataObject中公开一些额外的公共属性,以便在方法中将其设置为值。

Note : you will need to expose some extra public properties in DataObject so that they can be set as Values in the method.

看看你是如何得到的如果在CellValueNeeded方法中设置了一些断点,该方法应该有助于调试任何进一步的意外行为。祝你好运。

See how you get on with that. If you set some breakpoints within the CellValueNeeded method that should help with debugging any further unexpected behavior. Good luck.

这篇关于DataGridView虚拟模式,以简单的列表作为源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆