2012-05-07 11 views
2

我想爲ListBox使用Microsoft.Windows.APICodePack.Shell.ShellContainer作爲ItemsSource,通過ListBox.ItemTemplate顯示每個孩子的(ShellObject)縮略圖和名稱。 問題出現時ShellContainer指的是一個非常大的文件夾(說一千多個文件):如果我簡單地聲明最好的方法來設置BIG IEnumerable作爲ListBox.ItemSource

ShellContainer source=ShellObject.FromParsingName(@"C:\MyFolder") as ShellContainer: 
    listBox1.ItemsSource=source.GetEnumerator(); 

凍結了兩三分鐘的UI,然後顯示ShellContainer內容的一次。 我發現最好的解決方法是創建一個異步填料類這樣

class AsyncSourceFiller 
{ 
    private ObservableCollection<ShellObject> source; 
    private ShellContainer path; 
    private Control parent; 
    private ShellObject item; 

    public AsyncSourceFiller(ObservableCollection<ShellObject> source, ShellContainer path, Control parent) 
    { 
     this.source = source; 
     this.path = path; 
     this.parent = parent; 
    } 

    public void Fill() 
    { 
     foreach (ShellObject obj in path) 
     { 
      item = obj; 
      parent.Dispatcher.Invoke(new Action(Add)); 
      Thread.Sleep(4); 
     } 
    } 

    private void Add() 
    { 
     source.Add(item); 
    } 
} 

,然後通過

ObservableCollection<ShellObject> source = new ObservableCollection<ShellObject>(); 
    listBox1.ItemsSource = source; 
    ShellContainer path = ShellObject.FromParsingName(@"C:\MyFolder"): 
    AsyncSourceFiller filler = new AsyncSourceFiller(source, path, this); 
    Thread th = new Thread(filler.Fill); 
    th.IsBackground = true; 
    th.Start(); 

這需要比以前的方式更多的時間調用它,但不凍結用戶界面並立即開始顯示一些內容。 有沒有更好的方式來獲得類似的行爲,可能會縮短總的操作時間?

回答

1

加載後臺線程中的所有數據,並在完成更新listbox的itemssource時。並且不要忘記在列表框中將Virtualization設置爲true。

+0

謝謝。虛擬化解決了我的問題,但據我所知它只能通過VirtualizingStackPanel獲得,並且在我的ListBox中我需要一個WrapPanel。我正在調查自己實施一個可行性,但它似乎遠遠超出了我的卑微的技能,而不是談論第三方的選擇:或者他們是非常昂貴的,或者他們似乎是越野車和近似... – italianogrosso

0

耗時的操作是枚舉您的ShellContainer並創建數千個ShellObjectListBox不是問題。

當您將IEnumerable設置爲ItemControl的來源時,我認爲它首次顯示時會在枚舉數中創建並列出內部列表,這就是爲什麼它在顯示任何內容之前凍結了兩分鐘。

你沒有很多選擇在這裏:

  • 創建自己List<ShellObject>,並設置它作爲我們ListBox的來源。這不是更快,但至少可以向用戶顯示「正在加載,請稍候」消息。

  • 在另一個線程中加載列表(與您一樣),並在加載時顯示項目。隨着時間的推移,名單「增長」,這有點奇怪。

  • 找到一種方法來包裝你的ShellContainer在類實現IList。爲此,您需要能夠獲得ShellContainer類中的給定索引處的項目(我不知道「Windows API代碼包」)。如果您將此用作源ListBox並啓用了虛擬化,則只會顯示ShellObject s,並且它將快速而平穩。

+0

謝謝。請告訴我更多關於這個IList接口的信息,在我的情況下它怎麼可能有幫助... – italianogrosso