I have a WPF application using MVVM that utilises TreeViewItemViewModels to simplify working with a treeview as demonstrated by Josh Smith http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx
My treeview represents the records in a relational database and each node has its children loaded on demand. To improve the responsiveness of the UI I've been attempting to load the data asychronously using Tasks in .net 4.0 but am struggling to implement this satisfactorily.
The treeviewitemviewmodel IsExpanded property looks like this:
public bool IsExpanded
{
get { return _isExpanded; }
set
{
if (_isExpanded == value)
return;
if (!_isSelected)
IsSelected = true;
_isExpanded = value;
if (_isExpanded &&
_parent != null &&
_parent.GetType() != typeof(FirstGenerationViewModel))
_parent.IsExpanded = true;
ApplicationSetup.Messenger.NotifyColleagues(ApplicationSetup.MSG_WORKING, true);
Task task = Task.Factory.StartNew(() =>
{
LoadChildren();
})
.ContinueWith((t) =>
{
this.OnPropertyChanged("IsExpanded");
ApplicationSetup.Messenger.NotifyColleagues(ApplicationSetup.MSG_WORKING, false);
}, ApplicationSetup.UIScheduler);
}
}
If I select items manually and expand and collapse them all works as expected - a working animation is displayed, whilst LoadChildren() executes and then the items expand when OnPropertyChanged is called and the animation closes.
However, I'm trying to implement a search function. If a record is already loaded, I simply iterate the treeview until its found and then select it. However, if its not loaded the process should search the database for a record then display it. As records are loaded on demand, the process gets the sought item and its ancestors from the db and attempts to expand each ancestor in turn then finally selecting the sought item:
foreach (var item in ancestors.Keys)
{
TreeViewItemViewModel tv = _fgvm.recordsViewHelper.GetTreeViewItem(new ItemArgs
{
TargetTableName = item,
TargetPk = ancandtarget[item]
});
tv.IsExpanded = true;
}
If the sought item is high in the hierarchy, this works. However, when the record is nested a couple of items down, tv is null. I think this is because the item hasn't loaded before _fgvm.recordsViewHelper.GetTreeViewItem tries to locate it in the treeview.
How can I accomplish this? I've tried using Wait() but seem to freeze the UI.