我正在尝试在WPF中实现延迟树加载。我有一个TreeView
,我填充了一些节点。每个节点都有一个带有“正在加载...”标题的子节点。我想要实现的是:
foo
确定要添加的子节点。foo
已创建的新节点。我们的想法是向用户发送树正在加载的反馈,因为我的foo()
方法需要花费很长时间才能运行。
我的代码是:
<TreeView x:Name="MyTree" TreeViewItem.Expanded="MyTreeItem_Expanded" ItemsSource="{Binding}">
private void MyTreeItem_Expanded(object sender, RoutedEventArgs e) {
// some logic to figure out from which node the event has been risen
// method foo adds the new subnodes
// code which removes the "Loading..." subnode
}
通过此实现,当我单击节点时,树冻结,节点仅在foo()
完成后才会展开,并且“Loading ...”将被删除。
如何首先显示“正在加载...”节点,然后进行加载?
答案 0 :(得分:1)
因为主要ui线程项目上发生的一切似乎就像树视图一样冻结。如果可能的话,处理背景工作者的foo。 以下是来自wpf-tutorial.com的修改样本。这不是一个优化的解决方案,但会给你一个想法。
BackgroundWorker bgworker = new BackgroundWorker();
public MainWindow()
{
InitializeComponent();
bgworker.DoWork += bgworker_DoWork;
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo driveInfo in drives)
trvStructure.Items.Add(CreateTreeItem(driveInfo));
}
private void trvStructure_Expanded(object sender, RoutedEventArgs e)
{
TreeViewItem item = e.Source as TreeViewItem;
bgworker.RunWorkerAsync(item);
}
void bgworker_DoWork(object sender, DoWorkEventArgs e)
{
TreeViewItem item = (TreeViewItem)e.Argument;
LoadFiles(item);
}
void LoadFiles(TreeViewItem item)
{
System.Threading.Thread.Sleep(1000);
item.Dispatcher.BeginInvoke(new Action<TreeViewItem>(AddItems), item);
}
void AddItems(TreeViewItem item)
{
if ((item.Items.Count == 1) && (item.Items[0] is string))
{
item.Items.Clear();
DirectoryInfo expandedDir = null;
if (item.Tag is DriveInfo)
expandedDir = (item.Tag as DriveInfo).RootDirectory;
if (item.Tag is DirectoryInfo)
expandedDir = (item.Tag as DirectoryInfo);
try
{
foreach (DirectoryInfo subDir in expandedDir.GetDirectories())
{
item.Items.Add(CreateTreeItem(subDir));
}
}
catch { }
}
}
private TreeViewItem CreateTreeItem(object o)
{
TreeViewItem item = new TreeViewItem();
item.Header = o.ToString();
item.Tag = o;
item.Items.Add("Loading...");
return item;
}
LoadFiles(TreeViewItem item)
System.Threading.Thread.Sleep(1000);
中的正在为UI时间提供扩展。