WPF TreeView Lazy Loading


This entry is part 6 of 6 in the series WPF TreeView

WPF Tutorial says: “The usual process when using the TreeView is to bind to a collection of items or to manually add each level at the same time. However, in some situations, you want to delay the loading of a nodes child items until they are actually needed. This is especially useful if you have a very deep tree, with lots of levels and child nodes and a great example of this, is the folder structure of your Windows computer.”

Child folders are only loaded on demand. Also, as a side note in this example, you will notice that system files such as the swapfile.sys do not appear in the TreeView. You can find an explanation of the code over at WPF Tutorial in an article called Lazy loading TreeView items.

Here is the XAML code. It’s very simple.

<Window x:Class="TreeViewLazyLoading.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TreeViewLazyLoading"
        mc:Ignorable="d"
        WindowStartupLocation="CenterScreen"
        Title="TreeViewLazyLoading" Height="450" Width="400">
    <Grid>
        <TreeView Name="trvStructure" TreeViewItem.Expanded="TreeViewItem_Expanded"
                  Background="WhiteSmoke" Margin="10" />
    </Grid>
</Window>

Below is the code. Notice that all we do in the constructor (MainWindow()) is load the drive letters.

using System.IO;
using System.Windows;
using System.Windows.Controls;

namespace TreeViewLazyLoading
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DriveInfo[] drives = DriveInfo.GetDrives();
            foreach (DriveInfo driveInfo in drives)
                trvStructure.Items.Add(CreateTreeItem(driveInfo));
        }
        public void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
        {
            TreeViewItem item = e.Source as TreeViewItem;
            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;
        }
    }
}
Series Navigation<< WPF TreeView Selection/Expansion State