2010-10-08 40 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存儲在一個數組中。