I am working with data binding and tree views and I am not able to get my TreeView to populate in my WPF. I think I am relatively close, just a small tweak somewhere, but I can't seem to find it.
Here's my Project class:
public class Project { public Project(string Name, bool isFolder, Project ParentFolder) { this.Name = Name; this.isFolder = isFolder; Children = new List<Project>(); if (ParentFolder == null) { Path = Name; } else { Path = ParentFolder.Path + " > " + Name; } } public string Path { get; private set; } public string Name { get; set; } public bool isFolder { get; set; } public List<Project> Children { get; set; } public IEnumerable<Project> ChildFolders { get { return Children.Where(p => p.isFolder); } } public object Icon { get { if (isFolder) { return 0; // return folder icon } else { return 1; // return project icon } } } public IEnumerable<Project> SearchRecursively(string SearchString) { return GetAllChildren.Where(p => p.Name.Contains(SearchString)); } private List<Project> GetAllChildren { get { List<Project> allChildren = new List<Project>(); foreach(Project child in Children) { allChildren.AddRange(child.GetAllChildren); } return allChildren; } } } }
Here is my MaiWindow.xaml.cs class that I will be using to make test data:
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.BuildData(); } private void BuildData() { List<Project> parents = new List<Project>(); Project parentOne = new Project("Apple", true, null); Project parentTwo = new Project("Samsung", true, null); Project parentThree = new Project("Google", true, null); parents.Add(parentOne); parents.Add(parentTwo); parents.Add(parentThree); Project appleMacBook = new Project("Mac", false, parentOne); Project appleIpad = new Project("iPad", false, parentOne); Project appleiPhone = new Project("iPhone", false, parentOne); Project samsungGalaxy = new Project("Galaxy", false, parentTwo); Project samsungNote = new Project("Note", false, parentTwo); Project googlePixel = new Project("Pixel", false, parentThree); Project googleChromecast = new Project("Chromecast", false, parentThree); parents[0].Children.Add(appleMacBook); parents[0].Children.Add(appleIpad); parents[0].Children.Add(appleiPhone); parents[1].Children.Add(samsungGalaxy); parents[1].Children.Add(samsungNote); parents[2].Children.Add(googlePixel); parents[2].Children.Add(googleChromecast); } } } And here is my XAML where I am trying to display the TreeView. Right now, it is just blank. I would appreciate any tips.
<TreeView x:Name="Hierarchy" Grid.Column="4" HorizontalAlignment="Left" Height="631" Margin="0,58,0,0" Grid.Row="1" VerticalAlignment="Top" Width="265" ItemsSource="{Binding parents}"> <TreeView.ItemTemplate> <HierarchicalDataTemplate ItemsSource="{Binding parents}" DataType="{x:Type self:Project}"> <TreeViewItem Header="{Binding Name}"></TreeViewItem> </HierarchicalDataTemplate> </TreeView.ItemTemplate> Edit:
Here's the Property class:
public string Name { get { return name; } set { name = value; OnPropertyChanged("Name"); } } private string name { get; set; } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { if(PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } XAML:
<TreeView.ItemTemplate> <HierarchicalDataTemplate ItemsSource="{Binding ChildFolders}"> <StackPanel Orientation="Horizontal" > <Image Source="{Binding Icon}" Margin="5, 5, 5, 5"></Image> <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" BorderThickness="0" FontSize="16" Margin="5"/> </StackPanel> </HierarchicalDataTemplate> </TreeView.ItemTemplate> </TreeView> So, this doesn't seem to be firing the change event. I know this because Path is set as Name + ">". When I change the Name, Path is not reflecting the change. It only shows what my previous value for Name was, if that makes sense.
if (ParentFolder == null) { Path = Name; } else { Path = ParentFolder.Path + " > " + Name; } Edit:
public Project(string Name, bool isFolder, Project ParentFolder) { this.Name = Name; this.isFolder = isFolder; Children = new List<Project>(); this.ParentFolder = ParentFolder; } public string Path { get { return this.ParentFolder + " > " + this.Name; } set { this.Path = Path; } } XAML:
<TextBox x:Name="FolderNameBox" Grid.Column="1" Background="White" Grid.Row="1" Grid.ColumnSpan="5" Margin="0,0,287,654.333" VerticalContentAlignment="Center" Padding="6" FontSize="16" IsReadOnly="True" Text="{Binding ElementName=Hierarchy, Path=SelectedItem.Path, UpdateSourceTrigger=PropertyChanged}"> </TextBox> <TextBox x:Name="SearchProjectsBox" Grid.Column="5" Background="White" Grid.Row="1" Text="Search Projects" Margin="47.333,0,0,654.333" VerticalContentAlignment="Center" Foreground="LightGray" Padding="6" FontSize="16" HorizontalAlignment="Left" Width="268" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus"/> <TreeView x:Name="Hierarchy" Grid.Column="4" HorizontalAlignment="Left" Height="631" Margin="0,58,0,0" Grid.Row="1" VerticalAlignment="Top" Width="226" ItemsSource="{Binding Projects}"> <TreeView.ItemTemplate> <HierarchicalDataTemplate ItemsSource="{Binding ChildFolders}"> <StackPanel Orientation="Horizontal" > <Image Source="{Binding Icon}" Margin="5, 5, 5, 5"></Image> <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" BorderThickness="0" FontSize="16" Margin="5"/> </StackPanel> </HierarchicalDataTemplate> </TreeView.ItemTemplate> </TreeView> <Grid Grid.ColumnSpan="2" Grid.Column="4" HorizontalAlignment="Left" Height="631" Margin="245,58,0,0" Grid.Row="1" VerticalAlignment="Top" Width="540"> <ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"> <ListView Margin="0,0,10,0" Name="ProjectView" ItemsSource="{Binding Projects}" FontSize="16" Foreground="Black"> <ListView.View> <GridView ColumnHeaderContainerStyle="{StaticResource GridHeader}"> <GridViewColumn Header="Name" Width="200" DisplayMemberBinding="{Binding ElementName=Hierarchy, Path=SelectedItem.Name, UpdateSourceTrigger=PropertyChanged}"></GridViewColumn> <GridViewColumn Header="Directory" Width="328" DisplayMemberBinding="{Binding ElementName=Hierarchy, Path=SelectedItem.Path, UpdateSourceTrigger=PropertyChanged}"></GridViewColumn> </GridView> </ListView.View> </ListView> </ScrollViewer> </Grid> </Grid> The Path updates too but when it I see it it will display the path of the project rather than the fired change of name. It changes in real-time but doesn't save the String value..only registers that a change has happened.
Heres my Property Change too.
public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { if(PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }