I believe you are approaching this the wrong way. Most of your problems will disappear if you use DataBinding to populate your TreeView. Take into account the following class
namespace StackOverflow._20716616
{
public class Model
{
public Model()
{ Items = new ObservableCollection<Model>(); }
public Model(string text)
: this()
{ Text = text; }
public string Text { get; set; }
public ObservableCollection<Model> Items { get; set; }
}
}
Using this class as the model of an MVVM pattern, I can create a hierarchical object graph which I can bind to the TreeView using ItemsSource and a HierarchicalDataTemplate like
<TreeView ItemsSource="{Binding Path=Items}" SelectedItemChanged="TreeView_OnSelectedItemChanged">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type this:Model}" ItemsSource="{Binding Path=Items}">
<TextBlock Text="{Binding Path=Text}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
The DataContext of the window was set up on the root node of the xaml
DataContext="{Binding RelativeSource={RelativeSource Self}}"
In the code behind, I populate the root items of the TreeView
public MainWindow()
{
Items = new ObservableCollection<Model>() { new Model("one"), new Model("two"), new Model("three") };
InitializeComponent();
}
public ObservableCollection<Model> Items { get; set; }
Then, in the SelectedItemChanged, I can just add the children to the object graph
private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
var model = e.NewValue as Model;
if (!model.Items.Any())
{
new List<Model>() { new Model("one"), new Model("two"), new Model("three") }
.ForEach(model.Items.Add);
}
// expand the selected item.
var item = ((TreeView)sender).ItemContainerGenerator.ContainerFromItem(model) as TreeViewItem;
item.IsExpanded = true;
}
Note, this is poor man's MVVM where I have used the Windows code behind as the ViewModel. I have also left out null checks and exception catching for the sake of brevity.
I hope this helps