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));
}
}