问题
For my treeview I have two different classes that provide the ItemsSource.
public class TreeViewModel : ViewModelBase
{
public ObservableCollection<NodeViewModel> Items { get; set; }
}
public class NodeViewModel : ViewModelBase
{
public string Id { get; set; }
public string Name { get; set; }
public ObservableCollection<NodeViewModel> Children { get; set; }
}
Now I want my TreeView to display the Items in TreeViewModel and show hierarchical data as provided by the NodeViewModel.
Here is my XAML
<Window x:Class="TreeViewMasterDetails.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TreeViewMasterDetails"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TreeView Height="Auto"
HorizontalAlignment="Stretch"
Margin="10"
VerticalAlignment="Stretch"
Width="Auto">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="x:Type local:TreeViewModel" ItemsSource="{Binding Items}">
<TextBlock Text="{Binding Path=Name}"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="x:Type local:NodeViewModel" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}"></TextBlock>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
</Window>
Have tried to provide Items
as the ItemsSource
of the TreeView
.
It does not show the data hierarchically, if displaying anything.
And I tried using the ItemTemplate
instead of the TreeView.Resources
, too.
What is wrong about it?
Perhaps a problem is the first TextBlock Text Binding
?
I want to display the Name
property of the NodeViewModel
in Items
there.
回答1:
As @sa_ddam213 said, you only need the HierarchicalDataTemplate
for NodeViewModel
, but the only problem with your code was the missing braces ({
and }
) for DataType="x:Type local:TreeViewModel"
in your data template definitions (it should be DataType="{x:Type local:TreeViewModel}"
). Adding brackets and ItemsSource
binding solves the problem:
The additional HierarchicalDataTemplate
for TreeViewModel
is not used, but it does not harm.
回答2:
You should only have to declare the HierarchicalDataTemplate
for NodeViewModel
as this is the only thing showing in the TreeView
, and bind the actual ItemSource
to the TreeView
<TreeView ItemsSource="{Binding Items}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:NodeViewModel}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}"></TextBlock>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
Full Example
Xaml:
<Window x:Class="WpfApplication13.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication13"
Title="MainWindow" x:Name="UI" Width="343" Height="744.625" >
<TreeView DataContext="{Binding ElementName=UI, Path=TreeModel}" ItemsSource="{Binding Items}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:NodeViewModel}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}"></TextBlock>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Window>
Code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public TreeViewModel TreeModel
{
get
{
return new TreeViewModel
{
Items = new ObservableCollection<NodeViewModel>{
new NodeViewModel { Name = "Root", Children = new ObservableCollection<NodeViewModel> {
new NodeViewModel { Name = "Level1" , Children = new ObservableCollection<NodeViewModel>{
new NodeViewModel{ Name = "Level2"}}} } }}
};
}
}
}
public class TreeViewModel
{
public ObservableCollection<NodeViewModel> Items { get; set; }
}
public class NodeViewModel
{
public string Id { get; set; }
public string Name { get; set; }
public ObservableCollection<NodeViewModel> Children { get; set; }
}
Result:
来源:https://stackoverflow.com/questions/15240326/treeview-hierarchicaldatatemplate-and-recursive-data