2010-02-08 63 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框架,它有一些功能可以为你做这种事情。

相关问题