我有一个 TreeView 控件,我需要用大量的 3 层对象列表来填充它,这需要花费大量时间来构建。我正在后台线程上加载数据,然后将 GUI 更新发送到 GUI 线程,但是更新太多了,每次添加节点时我都必须发送它,然后我必须调用 ExpandSubTree() 方法然后展开所有子节点,然后触发更多展开事件,然后崩溃。
有没有一种方法可以在后台线程上建立控件并且它以某种方式处于打开/关闭状态,然后仅在完成后才将其编组?
每个树视图项都有一个属性 Children,如果将每个树视图项的子项绑定到 ObservableCollection,则可以从 BackGroundWorker 或其他线程向其添加项。如果您使用以下集合来绑定树视图项子项,您可以将子项从背景添加到视图。它使用同步上下文将项目添加到视图中:
public class ThreadSafeObservableCollection<T> : ObservableCollection<T>
{
private SynchronizationContext SynchronizationContext;
public ThreadSafeObservableCollection()
{
SynchronizationContext = SynchronizationContext.Current;
// current synchronization context will be null if we're not in UI Thread
if (SynchronizationContext == null)
throw new InvalidOperationException("This collection must be instantiated from UI Thread, if not, you have to pass SynchronizationContext to con structor.");
}
public ThreadSafeObservableCollection(SynchronizationContext synchronizationContext)
{
if (synchronizationContext == null)
throw new ArgumentNullException("synchronizationContext");
this.SynchronizationContext = synchronizationContext;
}
protected override void ClearItems()
{
this.SynchronizationContext.Send(new SendOrPostCallback((param) => base.ClearItems()), null);
}
protected override void InsertItem(int index, T item)
{
this.SynchronizationContext.Send(new SendOrPostCallback((param) => base.InsertItem(index, item)), null);
}
protected override void RemoveItem(int index)
{
this.SynchronizationContext.Send(new SendOrPostCallback((param) => base.RemoveItem(index)), null);
}
protected override void SetItem(int index, T item)
{
this.SynchronizationContext.Send(new SendOrPostCallback((param) => base.SetItem(index, item)), null);
}
protected override void MoveItem(int oldIndex, int newIndex)
{
this.SynchronizationContext.Send(new SendOrPostCallback((param) => base.MoveItem(oldIndex, newIndex)), null);
}
}
另外我认为这篇文章一定对你有用:
使用 ViewModel 模式简化 WPF TreeView
希望这对你有用...
你是在一次创建整棵树吗?您是否为创建的每个项目触发调用?
我会考虑按需加载树。也许当用户去扩展一个节点时,你处理那个事件并去获取数据。我还会考虑每次调用加载项目组