Reputation: 2458
I'm trying to bind an ObservableCollection to a treeview in WPF. It does kind-of work but not quite the way I thought it would.
This is the binding I have setup
<TreeView Height="250" ItemsSource="{Binding Path=TheUsers}" VerticalAlignment="Bottom" Width="500" Margin="0,39,0,0">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Permission}">
<TextBlock Text="{Binding}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
This is the collection it is binding to:
ObservableCollection<UserViewModel> theUsers;
public ObservableCollection<UserViewModel> TheUsers
{
get
{
return theUsers;
}
set
{
theUsers = value;
OnPropertyChanged("TheUsers");
}
}
This is the object in the collection:
public class UserViewModel
{
string userName = null;
public string UserName
{
get
{
return userName;
}
set
{
userName = value;
OnPropertyChanged("UserName");
}
}
int permCount = 0;
public int PermCount
{
get
{
return permCount;
}
set
{
permCount = value;
OnPropertyChanged("PermCount");
}
}
List<string> permission = null;
public List<string> Permission
{
get
{
return permission;
}
set
{
permission = value;
OnPropertyChanged("Permission");
}
}
This is what it displays
What I would like it to do is display the UserName for UserViewModel and the Permissions List<string>
items as the children. What is the proper way to do this ?
Thanks in Advance!
Upvotes: 2
Views: 2680
Reputation: 19020
You should be able to do this with a HierarchicalDataTemplate in addition to a normal DataTemplate
:
<TreeView Height="250" ItemsSource="{Binding Path=TheUsers}" VerticalAlignment="Bottom" Width="500" Margin="0,39,0,0">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:UserViewModel}" ItemsSource="{Binding Permission}">
<TextBlock Text="{Binding Path=UserName}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type sys:String}" >
<TextBlock Text="{Binding}" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
Add the following namespaces to your control/window:
xmlns:local="clr-namespace:WhateverYourAssemblyNamespaceIs"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Upvotes: 1
Reputation: 64949
With a bit of help from the MSDN DataTemplating overview, I think the following will do what you want. Note that I've added a top-level 'All Users' item to the treeview:
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:UserViewModel}" ItemsSource="{Binding Path=Permission}">
<TextBlock Text="{Binding Path=UserName}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type sys:String}">
<TextBlock Text="{Binding}"/>
</DataTemplate>
</Window.Resources>
...
<TreeView Height="250" VerticalAlignment="Bottom" Width="500" Margin="0,39,0,0">
<TreeViewItem ItemsSource="{Binding Path=TheUsers}" Header="All Users" />
</TreeView>
Replace the prefix local
with a namespace prefix bound to the namespace your UserViewModel class lives in.
You can set IsExpanded="True"
on the <TreeViewItem>
if you want the treeview to appear with the All Users item expanded.
Note that I used an ordinary DataTemplate
for the permissions, because I don't think you want the treeview to expand any further beyond a permission. (The tree could expand, because permissions are string
s, and string
s implement IEnumerable<char>
. If you tried to expand a string, you'd get a list of the individual characters of the string.)
Upvotes: 0
Reputation: 5785
Use a HierarchicalDataTemplate like
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:UserViewModel}" ItemsSource="{Binding Permission}" >
<TextBlock Text="{Binding UserName}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
Upvotes: 2