在WPF中加载惰性树

时间:2015-02-17 09:39:39

标签: c# wpf

我正在尝试在WPF中实现延迟树加载。我有一个TreeView,我填充了一些节点。每个节点都有一个带有“正在加载...”标题的子节点。我想要实现的是:

  1. 用户展开顶级节点。
  2. 顶级节点展开并显示“正在加载...”子节点。
  3. 显示加载节点后,方法foo确定要添加的子节点。
  4. 完成工作后,将删除“正在加载...”节点,并显示方法foo已创建的新节点。
  5. 我们的想法是向用户发送树正在加载的反馈,因为我的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 ...”将被删除。

    如何首先显示“正在加载...”节点,然后进行加载?

1 个答案:

答案 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时间提供扩展。