究竟是什么ListView.RetrieveVirtualItem事件 - C#

时间:2012-05-09 08:41:00

标签: c# winforms listview .net-3.5

对于Winforms App中的Virtual ListView控件, ALL RetrieveVirtualItem事件的功能是什么?

场景:有一个Dictionary对象充当我的ListView缓存。它的项目显示在ListView上。单击列时,缓存字典在内存中排序,ListView为Refresh()ed。对于UI的影响,ListView排序很好。 :)

但我想了解RetrieveVirtualItem事件的作用是什么,它在Refresh()上被触发。

在RetrieveVirtualItem事件处理程序[别人的代码中,:(],完成以下操作:

  1. 根据RetrieveVirtualItemEventArgs.ItemIndex,从缓存中获取消息
  2. 设置RetrieveVirtualItemEventArgs.Item =上面的

    看起来在事件处理程序中完成的操作很重要,因为如果我把它拿出来,ListView就会哭。这次活动有什么意义?

    修改 或者让我重新说一下这个问题......我关注的是,为什么在排序(和RetrieveVirtualItem事件处理程序)之后,所选项目保留在排序之前的位置。即,如果我选择项目#5并进行排序,如果排序将此项目作为最后一项,我希望在排序后选择最后一项。但在我的情况下,排序后选择第5项。那么RetrieveVirtualItem WRT选择项的默认行为是什么?

3 个答案:

答案 0 :(得分:4)

虚拟ListView只应为屏幕上当前可见的行调用RetreiveVirtualItem。

当您在ListView中导航时,例如,按下向下翻页键,ListView将计算现在应该是顶行的索引,然后调用RetrieveVirtualItem,以便您的代码可以提供要在每一行索引。

除非您通过RetrieveVirtualItem缓存或以其他方式存储您提供的项目,否则一旦它们滚动到列表视图之外它们将不再存在。

这就是VirtualListView中虚拟的含义 - 没有任何实际行,行是虚拟的。这就是它如何显示包含数十万行的列表 - 因为它实际上只包含屏幕上可见的行数。

实际上,ListView就像一个在内部数据列表中上下移动的窗口 - RetreiveVirtualItem方法是它在移动时将项目移动到该窗口的调用。它说,嘿,我刚刚搬到第15行 - 给我那一行的项目。它将继续为每个可见的行索引调用RetreiveVirtualItem。如果ListView在屏幕上的高度为5行,您将收到5次对RetrieveVirtualItem的调用 - 即使支持listview的实际数据有3000个项目。每次ListView的顶行发生变化(由于导航),你都会收到5次对RetrieveVirtualItem的调用(情况并非总是如此,但这是正确的想法 - 例如,如果向下滚动一行,它将只是问你新的最后一行 - 它也会简单地丢弃用于滚动出视图的旧顶行的数据。

我想如果我们假设ListView在显示屏上只有一行(意味着屏幕上只有一行实际可见),我可能会更容易解释 - 当您在列表中上下移动ListView时数据(即用户导航ListView),每次移动到新行时,它都会调用一次RetrieveVirtualItem。

希望有帮助...... 祝你好运

答案 1 :(得分:2)

RetrieveVirtualItem事件仅在ListView进入虚拟模式时使用。它不是在List集合中保留ListViewItems(当不在虚拟模式下时),而是在需要时动态创建ListViewItems。

如果您不处理RetrieveVirtualItem事件,则不会将ListViewItems添加到ListView中。我附加了一些示例代码,用于处理事件的典型方法:

  //Dynamically returns a ListViewItem with the required properties; in this case, the square of the index.
void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
    {
        //Check if cache has been instantiated yet, and if so, whether the item corresponding to the index requested has been added to the cache already
        if (myCache != null && e.ItemIndex >= firstItem && e.ItemIndex < firstItem + myCache.Length)
        {
            //Return cached item for index
            e.Item = myCache[e.ItemIndex - firstItem];
        }
        else
        {
            //When item not in cache (or cache not available) return a new ListViewItem
            int x = e.ItemIndex * e.ItemIndex;
            e.Item = new ListViewItem(x.ToString());
        }
    }

此示例取自MSDN(http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.virtualmode(v=vs.90).aspx),其中可以找到更多详细信息。

答案 2 :(得分:2)

虚拟列表视图仅处理索引。因此,如果在排序之前选择了第5项,则在排序后仍将选择第5项。控件本身无法知道过去第5行的数据现在是第一行。

您必须在排序方法中为自己编程:

  1. 记住选择了哪些项目(请记住:在虚拟模式下,您无法使用SelectedItems属性)
  2. 进行排序
  3. 现在找到以前所选项目的索引
  4. 选择那些指数
  5. 您可以在ObjectListView - 标准.NET ListView的包装器中看到所有这些内容。