Steve Bickell

Does anyone know how to load a TreeView node only when the user tries to expand it

In Win Forms I used to load a dummy child item for a node to cause the '+' to be shown and then catch the expanding event, delete the dummy item and load up the correct children for the node.

This meant that database access could be kept to a minimum.

I can't see any event for either the TreeView or TreeViewItem that is fired before a node is expanded.



Re: Windows Presentation Foundation (WPF) Loading TreeView nodes on demand

Thomas C. Huber

Hi Steve,

you could do exactly the same as in WinForms. The TreeViewItem has an Expanded-Event, that is fired when it's expanded. The cool thing in WPF is, that this Expanded-Event on a TreeViewItem is Bubbling. So you could use an attached Event on the TreeView to handle the Expand for every item in on place.

Following you see a treeview that explores the filesystem and is lazy-loading. I've just used a dummyNode, as you did before in winForms:

Code Snippet

<Window x:Class="WindowsApplication9.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="WindowsApplication9" Height="300" Width="300" Loaded="WindowLoaded"

>

<Grid>

<TreeView x:Name="fileSystemTreeView"/>

</Grid>

</Window>

Code Snippet

public partial class Window1 : System.Windows.Window

{

private object yourDummyNode = null;

public Window1()

{

InitializeComponent();

}

private void WindowLoaded(object sender, RoutedEventArgs e)

{

fileSystemTreeView.AddHandler(TreeViewItem.ExpandedEvent, new RoutedEventHandler(ItemExpanded));

foreach (string str in Environment.GetLogicalDrives())

{

TreeViewItem tvi = new TreeViewItem();

tvi.Header = str;

tvi.Tag = str;

tvi.Items.Add(yourDummyNode);

fileSystemTreeView.Items.Add(tvi);

}

}

private void ItemExpanded(object sender, RoutedEventArgs e)

{

TreeViewItem item = e.OriginalSource as TreeViewItem;

if (item != null)

{

if (item.Items.Count == 1 && item.Items[0] == yourDummyNode)

{

item.Items.Clear();

try

{

foreach (string str in Directory.GetDirectories(item.Tag.ToString()))

{

TreeViewItem subitem = new TreeViewItem();

subitem.Header = str.Substring(str.LastIndexOf('\\') + 1);

subitem.Tag = str;

subitem.Items.Add(yourDummyNode);

item.Items.Add(subitem);

}

}

catch (UnauthorizedAccessException ex)

{

}

catch (IOException ex)

{

}

}

}

}

}

Helpful for you






Re: Windows Presentation Foundation (WPF) Loading TreeView nodes on demand

Steve Bickell

Thanks Thomas, I don't know how I missed it.





Re: Windows Presentation Foundation (WPF) Loading TreeView nodes on demand

Jérémy Alles

Hi,

I would like to do the same thing, but my treeview uses DataBinding :

<TreeView DockPanel.Dock="bottom" x:Name="XCollection" Width="200">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource = "{Binding Path=ChildMusicItem}">
<StackPanel>
<TextBlock Text="{Binding Path=Name}"/>
<TextBlock Text="{Binding Path=Level}"/>
<TextBlock Text="{Binding Path=ParentMusicItem.Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>

class MusicItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

public MusicItem()
{
this.childMusicItem = new ObservableCollection<MusicItem>();
}

...
private ObservableCollection<MusicItem> childMusicItem;

public ObservableCollection<MusicItem> ChildMusicItem
{
get
{
retrieve child from database, long operation if I do it for all top
level item
}
}
}

Do you have any idea about how shoud I do

Regards,
Jeremy