Reputation: 4984
I made a shot app to exemplify my question:
Heres the window1.xaml
<Window
x:Class="TreeViewStepByStep.Window1"
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:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Width="400"
Height="600">
<Window.Resources />
<Grid>
<TreeView
Margin="0,21,0,0"
ItemsSource="{Binding Regions}"
HorizontalAlignment="Left"
Width="221">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate
ItemsSource="{Binding Type}">
<TextBlock
Text="{Binding Name}" />
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate
ItemsSource="{Binding Locations}">
<TextBlock
Text="{Binding Name}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock
Text="{Binding}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<Button
Content="Populate"
Height="23"
HorizontalAlignment="Left"
Margin="227,21,0,0"
Name="button2"
VerticalAlignment="Top"
Width="96"
Click="button2_Click" />
<Button
Content="Add child"
Height="23"
HorizontalAlignment="Left"
Margin="227,49,0,0"
Name="button3"
VerticalAlignment="Top"
Width="96"
Click="button3_Click" />
<Button
Content="Modify"
Height="23"
HorizontalAlignment="Left"
Margin="227,106,0,0"
Name="button4"
VerticalAlignment="Top"
Width="96"
Click="button4_Click" />
<Button
Content="Add root level"
Height="23"
HorizontalAlignment="Left"
Margin="227,135,0,0"
Name="button5"
VerticalAlignment="Top"
Width="96"
Click="button5_Click" />
</Grid>
</Window>
And here's the window1.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
namespace TreeViewStepByStep
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
Collection<Region> regions;
public Window1()
{
InitializeComponent();
}
private void button2_Click(object sender, RoutedEventArgs e)
{
Region sms = new Region("São Mateus do Sul")
{
Type =
{
new Types("Placemarks")
{
Locations =
{
"Pine trees",
"Barn",
"Phantom city"
}
},
new Types("Planning")
{
Locations =
{
"Geada",
"Por do sol"
}
},
}
};
Region others = new Region("Outros")
{
Type =
{
new Types("Placemarks")
{
Locations =
{
"Road",
"Waterfall"
}
},
new Types("Planning")
{
Locations =
{
"Moon"
}
},
}
};
regions = new Collection<Region>() { sms, others };
DataContext = new
{
Regions = regions
};
}
private void button3_Click(object sender, RoutedEventArgs e)
{
this.regions[1].Type.Add(new Types("New folder")
{
Locations =
{
"Test"
}
}
);
}
private void button4_Click(object sender, RoutedEventArgs e)
{
this.regions[0].Name = "Edited";
}
private void button5_Click(object sender, RoutedEventArgs e)
{
this.regions.Add(new Region("My new region"));
}
}
public class Region
{
public Region(string name)
{
Name = name;
Type = new ObservableCollection<Types>();
}
public string Name { get; set; }
public ObservableCollection<Types> Type { get; set; }
}
public class Types
{
public Types(string name)
{
Name = name;
Locations = new ObservableCollection<string>();
}
public string Name { get; private set; }
public ObservableCollection<string> Locations { get; set; }
}
}
My TreeView
is bound to a hierarchical model (the regions variable). When I click "Populate" it binds the TreeView
to this variable. When I click "Add Child" it adds a child element to the bound variable and it reflects on the TreeView
. So far so good.
The problem arises when I try to modify the name of an existing element or try to add a root level node ("Modify" and "Add Root Level" buttons). Shouldn't these modifications reflect on the TreeView
as well since it's bound to the collection?
Upvotes: 1
Views: 192
Reputation: 3302
As you have it now, the Collection
will not notify the view when it is changed. You want to use an ObservableCollection instead of a normal Collection<T>
. The ObservableCollection
is coded to work with the UI and make sure the view is always updated with those changes through the CollectionChanged
event. You use ObservableCollection
with some of the others, but your Regions variable is a Collection.
Upvotes: 2
Reputation: 1584
You need to change the Collection
type to ObservableCollection
and needs to implement INotifyPropertyChanged
on region class to send notification to View on edit.
C# Window Class:
ObservableCollection<Region> regions;
Region Class:
public class Region : INotifyPropertyChanged
{
public Region(string name)
{
Name = name; Type = new ObservableCollection<Types>();
}
private string name;
public string Name
{
get { return name; }
set
{
name = value;
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
public ObservableCollection<Types> Type { get; set; }
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged = (s, e) => { };
#endregion
}
Upvotes: 1