2010-02-08 65 views
1

我有一個TreeView 1000個項目。當我選擇一個項目時,TreeView會觸發一個事件,以便我可以更新GUI中的某些內容。事件處理程序是非遞歸的,並且沒有循環,但它需要一點時間才能完成,可能是100ms。如果SelectionChanged事件觸發得太快,WPF Treeview的stackoverflow?

如果我選擇頂部的項目,並使用向下的箭頭滾動項目緩慢,一切工作正常,但如果我按住箭頭鍵,事件觸發得太快,我得到一個stackoverflow例外。

我想過在TreeView中放置一個定時器,所以SelectionChanged事件只能每隔100ms左右發射一次,但這看起來很駭人聽聞。任何想法來解決這個問題?

+0

當用戶快速瀏覽列表時,您是否確實需要更新UI中的某些內容? – arconaut 2010-02-08 21:13:49

+0

可能不是當他們快速滾動時,但我怎麼知道他們是否快速滾動? – user113164 2010-02-08 21:20:18

回答

3

我見過類似的東西也發生在winforms上。我看到人們實現的一種方式是延遲事件處理程序。只有在指定的時間段內選擇了該項目後纔會觸發。

所以工作的方式是你有一個事件處理程序執行一個計時器。只要發生selectionchanged事件,計時器就會重置。你的計時器可能是500毫秒,所以如果在500毫秒後選定的值仍然被選中,它將觸發你需要處理的實際事件代碼。

不是說這是最好的方式,只是我看到它在Windows窗體中處理的一種方式。

1

異步運行事件處理程序。這樣做的最簡單的方法如下:

void SelectionEventHandler(object sender, EventArgs e) 
{ 
    var ownerElement = sender as FrameworkElement; // this should be the TreeView itself 
    ThreadPool.QueueUserWorkItem(o => { 

     // Do stuff 

     ownerElement.Dispatcher.BeginInvoke(new Action(() => { 

      // Update UI in response to stuff being done 

     }); 
    }); 
} 

如果你使用類似The Reactive Framework,那麼你可以減少參與的線程池的克魯夫特等頗大。

您可能還會考慮並行任務庫,它的Task<T>類 - 您可以通過下載反應性框架來獲得.NET 3.5版本。

注意:異步運行處理程序應該停止堆棧溢出,但是當用戶向下滾動列表時,它不會停止處理器運行1000次。如果你想這樣做,你可以實現一個延遲計時器,或者如果你使用Reactive框架,它有一些功能可以爲你做這種事情。

相關問題