对于Winforms App中的Virtual ListView控件, ALL RetrieveVirtualItem事件的功能是什么?
场景:有一个Dictionary对象充当我的ListView缓存。它的项目显示在ListView上。单击列时,缓存字典在内存中排序,ListView为Refresh()ed。对于UI的影响,ListView排序很好。 :)
但我想了解RetrieveVirtualItem事件的作用是什么,它在Refresh()上被触发。
在RetrieveVirtualItem事件处理程序[别人的代码中,:(],完成以下操作:
RetrieveVirtualItemEventArgs.ItemIndex
,从缓存中获取消息RetrieveVirtualItemEventArgs.Item
=上面的看起来在事件处理程序中完成的操作很重要,因为如果我把它拿出来,ListView就会哭。这次活动有什么意义?
修改
或者让我重新说一下这个问题......我关注的是,为什么在排序(和RetrieveVirtualItem
事件处理程序)之后,所选项目保留在排序之前的位置。即,如果我选择项目#5并进行排序,如果排序将此项目作为最后一项,我希望在排序后选择最后一项。但在我的情况下,排序后选择第5项。那么RetrieveVirtualItem
WRT选择项的默认行为是什么?
答案 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行的数据现在是第一行。
您必须在排序方法中为自己编程:
SelectedItems
属性)您可以在ObjectListView - 标准.NET ListView的包装器中看到所有这些内容。