I have a TreeView control that I need to populate with a large 3 tiered list of objects which is taking an incredible amount of time to build up. I'm doing the loading of the data on the background thread then sending the GUI updates over to the GUI thread, but there are just too many updates, for every time I add a node I have to send that across, then I have to call the ExpandSubTree() method to then expand all the sub nodes, which then fires off more expand events, and it crashes.
Is there a way I can build up the control and it's open/closed state somehow on a background thread and then only marshall it over once it's complete?
Each tree view item had a property Children, if you bind each Tree View Item's Children to an ObservableCollection you may add item to it from a BackGroundWorker or another thread. If you use the follow collection to bind the tree view item children you may add-remove children from background to the view. It use a synchronization context to add items to the view:
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);
}
}
Also i think that this articles must be useful to you:
Simplifying the WPF TreeView by Using the ViewModel Pattern
Hope this would be useful for you...