This example works, though it's only two (not 3) levels deep. It shows a simple 2-level hierarchical treeview with parent items A, B, and C, with numbered children (A.1, B.1, etc). When the Rename B.1 button is clicked, it renames B.1 to "Sylvia".
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace UpdateVanillaBindingValue
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private DataClass _data;
public Window1()
{
InitializeComponent();
var data = CreateData();
DataContext = _data = data;
}
private DataClass CreateData()
{
return new DataClass
{
Parents=new List<Parent>
{
new Parent{Name="A",Children=new List<Child>{new Child{Name="A.0"},new Child{Name="A.1"}}},
new Parent{Name="B",Children=new List<Child>{new Child{Name="B.0"},new Child{Name="B.1"},new Child{Name="B.2"}}},
new Parent{Name="C",Children=new List<Child>{new Child{Name="C.0"},new Child{Name="C.1"}}}
}
};
}
private void Rename_Click(object sender, RoutedEventArgs e)
{
var parentB = _data.Parents[1];
var parentBItem = TheTree.ItemContainerGenerator.ContainerFromItem(parentB) as TreeViewItem;
parentB.Children[1].Name = "Sylvia";
var parentBItemsSource = parentBItem.ItemsSource;
parentBItem.ItemsSource = null;
parentBItem.ItemsSource = parentBItemsSource;
}
}
public class DataClass
{
public List<Parent> Parents { get; set; }
}
public class Parent
{
public string Name { get; set; }
public List<Child> Children { get; set; }
}
public class Child
{
public string Name { get; set; }
}
}
<Window x:Class="UpdateVanillaBindingValue.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Grid.Resources>
<DataTemplate x:Key="ChildTemplate">
<TextBlock Margin="50,0,0,0" Text="{Binding Name}" />
</DataTemplate>
<HierarchicalDataTemplate x:Key="ParentTemplate" ItemsSource="{Binding Children}" ItemTemplate="{StaticResource ChildTemplate}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</Grid.Resources>
<TreeView x:Name="TheTree" ItemsSource="{Binding Parents}" ItemTemplate="{StaticResource ParentTemplate}" />
<Button VerticalAlignment="Bottom" HorizontalAlignment="Center" Content="Rename B.1" Click="Rename_Click" />
</Grid>
</Window>
This is a hack, but it re-evaluates the DataTemplate every time it's ItemsSource property changes.
Ideally, you would implement INotifyPropertyChanged on your model object class that this TreeViewItem is bound to, and have it fire the PropertyChanged event when that value changes. In fact, you should be careful that you aren't incurring a memory leak because it doesn't: Finding memory-leaks in WPF Applications.