2013-03-06 2 views
13

Для моего treeview у меня есть два разных класса, которые предоставляют ItemSource.TreeView, HierarchicalDataTemplate и рекурсивные данные

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

Теперь я хочу, чтобы мой TreeView для отображения элементов в TreeViewModel и показывать иерархические данные, предоставляемые NodeViewModel.

Вот мой 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> 

Пытались обеспечить Items как ItemsSource в TreeView. Он не отображает данные иерархически, если отображается что-либо.

И я пробовал использовать ItemTemplate вместо TreeView.Resources.

Что не так?

Возможно, проблема в первом TextBlock Text Binding? Я хочу показать Name собственность NodeViewModel в Items.

+0

Я думаю, что это дубликат [WPF TreeView HierarchicalDataTemplate - привязка к объекту с несколькими дочерними коллекциями] [1]. [1]: http://stackoverflow.com/questions/1912481/wpf-treeview-hierarchicaldatatemplate-binding-to-object-with-multiple-child-co – Schollii

+0

Да, я уже видел, что. Но здесь это не работает. –

+0

См. Мой обновленный вопрос –

ответ

3

Как @ sa_ddam213 сказал, что вам нужно только HierarchicalDataTemplate для NodeViewModel, но единственная проблема с кодом был недостающие скобки ({ и }) для DataType="x:Type local:TreeViewModel" в вашем определения шаблонов данных (это должно быть DataType="{x:Type local:TreeViewModel}"). Добавление скобок и ItemsSource связывание решает проблему:

Дополнительный HierarchicalDataTemplate для TreeViewModel не используется, но это не вредит.

+0

Вы правы, это действительно проблема. Как ни странно, он работает без брекетов при использовании в 'ItemTemplate', но не в' Resources'. –

+0

@MareInfinitus Это связано с тем, что при использовании int 'ItemTemplate' он не должен искать свойство' DataType'. Вы прямо говорите «TreeView», чтобы использовать данный шаблон для элементов. Поэтому нет необходимости в «DataType». –

23

Вы должны только объявить HierarchicalDataTemplate для NodeViewModel, поскольку это единственное, что показ в TreeView, и связать фактическую ItemSource с 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> 

Полный пример

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> 

Код:

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

Результат:

enter image description here

+0

Да, это работает. Был уверен, что я пробовал это раньше. Спасибо огромное! –

+0

Привет, спасибо за обмен, я использовал ваше решение, однако, похоже, он не позволяет мне выбрать anyhting, а также стрелки слева отсутствуют.Дерево выглядит замороженным. Одно изменение, которое я сделал с вами, я привязываю свой TreeModel из класса ViewModel, а не из MainWindow. –

+0

Работал хорошо для меня. Также см. Https://stackoverflow.com/questions/2251260/, если вы хотите, чтобы CheckBoxes распространялись вместо TextBlocks. – Chris