2010-10-08 105 views
0

问题可能很简单,该帖子比我想要的要长,但我已尽量提供尽可能多的信息和详细信息。 我没有写这个GUI应用程序,也没有设计,但是我们大多数人都继承了它。listview虚拟列表,e.ItemIndex崩溃!

它有一个(常规)ListView,实际上该应用程序有几个ListView(s),不知道如果那很重要。 因为到达这一个ListView(屏幕/窗体)的项目数可以变得非常大10K +我决定将它转换为虚拟列表,但是我遇到了一些早期问题。

最大的问题之一是,通过点击表单上的按钮来异步填充项目。 当它们到达时(从服务/网络/数据库),这些项目被构建到ListViewItem中并被添加到ArrayList的某个ListItems中。

在我RetrieveVirtualItem方法,我需要处理这两种情况时,该列表是空的,当我已经有一些(按钮被击中后),这时候我撞到墙(没有双关语意) 与以下行代码:

if (someListItems.Count > e.ItemIndex) 

它主要导致(不知道为什么)调用主窗体上的Dispose方法,导致整个应用程序崩溃困难。但是,只有当我点击表格和列表时才会发生。如果表单刚刚被加载并填充,那很好..第二次,你点击鼠标,BOOM!

我花了几个小时才弄清楚上面的这条线是罪魁祸首,因为调用栈并不是非常明显的指出这一点,而另一分钟则发现e.ItemIndex是罪魁祸首。但为什么???我 n msdn示例他们访问e.ItemIndex来执行测试,它似乎很好。

虚拟模式设置在窗体的构造函数:

myListView.VirtualMode = true; 

VirtualListSize的数据后立即设置异步到达:

myListView.VirtualListSize = someArrayList.Count; 

这是我RetrieveVirtualItem实现:

private void blah_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) 
{ 
// someListItems is an ArrayList that is created when the object/class loads..and populated with ListViewItems. 
// i.e. private ArrayList someListItems = new ArrayList(); 
// it is populated asynchronously by hitting a button on the form, hence it's empty when the form loads.. 
     if (someListItems.Count <= 0) 
     { 
     e.Item = new ListViewItem(""); 
     e.Item.SubItems.Add(""); 
     e.Item.SubItems.Add(""); 
     } 
     else 
     { 
// the of code below is the problem, and more specifically - e.ItemIndex causes somehow to call Dispose on the main form.. 
// the reason I have this code is because if I take it out, all items will show up, no problem, but it will crash when I try to scroll down.. 
// with message like this: 
// Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index 

    if (someListItems.Count > e.ItemIndex)    
    { 
    // took out my code out to eliminate possibility that it's my code. :) 
    int x = e.ItemIndex * e.ItemIndex; 
    e.Item = new ListViewItem(x.ToString()); 

    // but I had something like that just for a test: 
    // ListViewItem item = (ListViewItem)someListItems[e.ItemIndex]; 
    // e.Item = item; 
    // remember that someListItems already has ListViewItems 
    } 
    }  
} 

异步调用的方法创建ListViewItems和po pulates someListItems看起来就像这样:

private void ExampleMethod_That_PopulatesSomeArrayList(ArrayList ar) 
{ 
//Im only showing more essential code.. 

    SomeArrayList.Items.Clear(); 
    myListView.VirtualListSize = ar.Count; 
    foreach (SomeObject o in ar) 
    { 
    ListViewItem lvi = new ListViewItem(SomeObject.somePropertyID, 0); 
// I've tried changing the above line to: lvi = new ListViewItem(SomeObject.somePropertyID, 0); // and having the ListViewItem lvi on the class level. i.e private ListViewItem lvi 
// didn't help.. :(

    lvi.SubItems.Add(o.someProperty1); 
    lvi.SubItems.Add(o.someProperty2); 
// there's quite few of these subitems..2 is enough for this example... 
    } 

// the orignal code, before I changed it to virtual list was adding the items somewhere here..after finished looping, now I'm just trying to reuse that array of ListViewItems. 
} 

还有另一个问题,即项目真的不显示在所有除非我拿出了:

if (someListItems.Count > e.ItemIndex) 

但后来我遇到了指数范围问题,当我尝试滚动。


UPDATE:

我发现,如果我设置虚拟目录的大小,只在循环结束后,因此它是零(0)开头(我总能它重置为零),则一切正常,不需要检查大小,所有我需要做的就是这个:private void ExampleMethod_That_PopulatesSomeArrayList(ArrayList ar)

this.myListView.VirtualListSize = someListItems.Count; 

在循环后3210

,我想感谢Hans Passant注意到这种差异。 所以这是完整的,现在(我敢肯定,我会添加一些代码或改变,因为我想添加一些缓存,但至少我有什么...

private void blah_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) 
{ 
    e.Item = (ListViewItem)someListItems[e.ItemIndex]; 
} 

唯一我不知道什么汉斯帕桑特提到的事情是这样的:“真的是不行的此事件处理程序从未分配的ListViewItem。”这我不知道如果我理解,因为ListViewItems分配并插入到someListItems数组中,我确实有过尝试,并且之前也做过。另外,我在想,我会喜欢上这种想法的人的输入: 创建一个单独的对象,将持有SomeObject的所有性的判定或插入SomeObject(S)到列表,并根据需要创建新的ListViewItems? e.g:

private void blah_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) 
    { 
     // that list would be build sometime during the loop iteration in 
     // (I'm using the original method name mentioned way above in this post) 
     // ExampleMethod_That_PopulatesSomeArrayList(ArrayList ar) 

     SomeObject o = listOfObjects[e.ItemIndex]; 
     e.Item = new ListViewItem(); 
     e.Item.SubItems.Add(o.prop1); 
     e.Item.SubItems.Add(o.prop2); 
     e.Item.SubItems.Add(o.prop3);   
    } 
+0

什么是异常和堆栈跟踪? – SLaks 2010-10-08 15:56:53

回答

1

要回答这个问题。由于VirtualListSize设置不正确,虚拟列表崩溃。 基本上,为了帮助这里的其他人,如果您有虚拟列表,请务必确保VirtualListSize与您尝试显示的实际项目数相对应。如果不是,所有的地狱都会破裂。如果您更新,删除,添加任何内容,则需要将VirtualListSize重置为正确的数字。

我最终从ListView派生并将我的listviewitems存储在一个数组中。