WPF TreeView - привязка к моделям представления с вложенными коллекциями и «статическими узлами» - PullRequest
1 голос
/ 12 февраля 2011

Я рассмотрел похожие вопросы, касающиеся привязки данных TreeView к вложенным коллекциям, и я прочитал несколько статей "Josh 'n Bea" на эту тему, но мой дизайн отличается тем, что у меня есть "static" TreeViewItems которые служат складными контейнерами для вложенных элементов коллекции. Лучше всего проиллюстрировать, что я ищу.

С учетом этих классов ViewModel:

namespace TreeViewSample
{
    public class ApplicationViewModel
    {
        public ApplicationViewModel() { Projects = new List<ProjectViewModel>(); }
        public IEnumerable<ProjectViewModel> Projects { get; set; }
    }

    public class ProjectViewModel
    {
        public ProjectViewModel() { Maps = new List<MapViewModel>(); }
        public string Name { get; set; }
        public IEnumerable<MapViewModel> Maps { get; set; }
    }

    public class MapViewModel
    {
        public MapViewModel() { Tables = new List<TableViewModel>(); }
        public string Name { get; set; }
        public IEnumerable<TableViewModel> Tables { get; set; }
    }

    public class TableViewModel
    {
        public TableViewModel() { Fields = new List<FieldViewModel>(); }
        public string Name { get; set; }
        public IEnumerable<FieldViewModel> Fields { get; set; }
    }

    public class FieldViewModel
    {
        public string Name { get; set; }
    }
}

Это результат, который я хочу:

enter image description here

Может ли кто-нибудь помочь мне с XAML для этого TreeView? Я думал, что понял, как работает HierarchicalDataTemplates, но «статические» контейнерные узлы («Таблицы», «Поля», «Карты»), кажется, смущают меня.

Спасибо и приятного дня!

1 Ответ

2 голосов
/ 13 февраля 2011

Я думаю, вам нужно будет создать HierarchicalDataTemplate s для "статических" узлов. И так как ItemsSource для HierarchicalDataTemplate ожидает коллекцию, вы можете создать эти коллекции в Xaml следующим образом

* Namespaces 1006 *

xmlns:coll="clr-namespace:System.Collections;assembly=mscorlib"
xmlns:sys="clr-namespace:System;assembly=mscorlib"

Коллекция

<coll:ArrayList x:Key="MapCollection">
    <sys:String>Maps</sys:String>
</coll:ArrayList>
<coll:ArrayList x:Key="TableCollection">
    <sys:String>Tables</sys:String>
</coll:ArrayList>
<coll:ArrayList x:Key="FieldCollection">
    <sys:String>Fields</sys:String>
</coll:ArrayList>

Проблема с этим решением заключается в том, что при установке, например, MapCollection как ItemsSource для HierarchicalDataTemplate, у вас не будет доступа к Maps свойству Collection на следующем уровне, поэтому вам придется взобраться на Visual Tree, чтобы получить его, как

ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}},
                      Path=DataContext.Maps}"

Используя этот подход, ваши HierarchicalDataTemplate могут выглядеть следующим образом

<!-- Field Templates -->
<HierarchicalDataTemplate x:Key="FieldsTemplate">
    <TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="FieldTemplate"
                          ItemTemplate="{StaticResource FieldsTemplate}"
                          ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}},
                                                Path=DataContext.Fields}">
    <TextBlock Text="{Binding}"/>
</HierarchicalDataTemplate>

<!-- Table Templates -->
<HierarchicalDataTemplate x:Key="TablesTemplate"
                          ItemTemplate="{StaticResource FieldTemplate}"
                          ItemsSource="{Binding Source={StaticResource FieldCollection}}">
    <TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="TableTemplate"
                          ItemTemplate="{StaticResource TablesTemplate}"
                          ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}},
                                                Path=DataContext.Tables}">
    <TextBlock Text="{Binding}"/>
</HierarchicalDataTemplate>

<!-- Map Templates -->
<HierarchicalDataTemplate x:Key="MapsTemplate"
                          ItemTemplate="{StaticResource TableTemplate}"
                          ItemsSource="{Binding Source={StaticResource TableCollection}}">
    <TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="MapTemplate"
                          ItemTemplate="{StaticResource MapsTemplate}"
                          ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}},
                                                Path=DataContext.Maps}">
    <TextBlock Text="{Binding}"/>
</HierarchicalDataTemplate>

<!-- Project Template -->
<HierarchicalDataTemplate x:Key="ProjectDataTemplate"
                          ItemTemplate="{StaticResource MapTemplate}"
                          ItemsSource="{Binding Source={StaticResource MapCollection}}">
    <TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>

TreeView

<TreeView Name="treeView"
          ItemTemplate="{StaticResource ProjectDataTemplate}"
          ItemsSource="{Binding Projects}"/>
...