我有一个使用MVVM的WPF应用程序,它利用TreeViewItemViewModels简化了使用树视图的工作,如Josh Smith http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx
所示我的treeview表示关系数据库中的记录,每个节点都按需加载其子节点。为了提高UI的响应能力,我一直在尝试使用.net 4.0中的任务异步加载数据,但我很难令人满意地实现这一点。
treeviewitemviewmodel IsExpanded属性如下所示:
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);
}
}
如果我手动选择项目并展开和折叠它们都按预期工作 - 显示工作动画,同时执行LoadChildren(),然后在调用OnPropertyChanged并关闭动画时展开项目。
但是,我正在尝试实现搜索功能。如果已加载记录,我只需迭代树视图直到找到它,然后选择它。但是,如果未加载,则进程应在数据库中搜索记录然后显示它。当记录按需加载时,进程从数据库中获取所需项目及其祖先,并尝试依次扩展每个祖先,然后最终选择所需项目:
foreach (var item in ancestors.Keys)
{
TreeViewItemViewModel tv = _fgvm.recordsViewHelper.GetTreeViewItem(new ItemArgs
{
TargetTableName = item,
TargetPk = ancandtarget[item]
});
tv.IsExpanded = true;
}
如果所寻求的项目在层次结构中很高,则可行。但是,当记录嵌套了几个项目时,tv为空。我认为这是因为在_fgvm.recordsViewHelper.GetTreeViewItem尝试在树视图中找到它之前,项目尚未加载。
我怎样才能做到这一点?我尝试过使用Wait()但似乎冻结了UI。
答案 0 :(得分:0)
我自己解决了这个问题。真的很明显。我现在使用包装器方法来扩展foreach循环中的祖先,它返回IsExpanded属性使用的任务。然后,此任务可以调用Wait(),以确保下一个祖先的父级在继续之前完全加载。