TreeView

64

Элемент управления TreeView является одним из главных элементов Windows и встречается довольно часто во всем, начиная от программы для просмотра файлов (проводник Windows) и заканчивая библиотекой справочной информации по .NET. Предлагаемая в WPF реализация TreeView впечатляет, поскольку обладает всей необходимой поддержкой для привязки данных.

Элемент управления TreeView, по сути, представляет собой специализированный класс ItemsControl, предназначенный для обслуживания объектов TreeViewItem. Но в отличие от ListViewItem, объекты TreeViewItem не являются элементами управления содержимым. Вместо этого каждый из них представляет собой отдельный класс ItemsControl, способный хранить дополнительные объекты TreeViewItem. Такая гибкость позволяет создавать многоуровневые представления данных.

Формально класс TreeViewItem наследуется от класса HeaderedItemsControl, который, в свою очередь, унаследован от ItemsControl. Класс HeaderedItemsControl имеет дополнительное свойство Header, в котором размещается содержимое (обычно текст), которое должно отображаться для данного элемента в дереве. В WPF доступны два других класса HeaderedItemsControl — MenuItem и Toolbar.

Ниже приведена схема простейшего элемента управления TreeView, который объявляется полностью в разметке:

<TreeView>
      <TreeViewItem Header="Fruit">
               <TreeViewItem Header="Lime"></TreeViewItem>
               <TreeViewItem Header="Orange"></TreeViewItem>
               <TreeViewItem Header="Apple"></TreeViewItem>
      </TreeViewItem>
      <TreeViewItem Header="Colors">
               <TreeViewItem Header="Red"></TreeViewItem>
               <TreeViewItem Header="Orange"></TreeViewItem>
               <TreeViewItem Header="Green"></TreeViewItem>
      </TreeViewItem>
</TreeView>

Конструировать TreeView из объектов TreeViewItem вовсе не обязательно. На самом деле в TreeView разрешено добавлять практически любые элементы, включая кнопки, панели и изображения. Однако когда требуется отобразить нетекстовое содержимое, лучше все-таки использовать класс-оболочку TreeViewItem и предоставлять это содержимое через свойство TreeViewItem.Header. Это равнозначно добавлению элементов, отличных от TreeViewItem, непосредственно в TreeView, но упрощает управление специфическими деталями TreeView вроде выбора и разворачивания узлов. При желании отобразить нe UIElement-объект, его можно отформатировать за счет использования шаблонов данных со свойством HeaderTemplate или HeaderTemplateSelector.

Привязка данных к элементу управления TreeView

Обычно элемент управления TreeView не заполняется фиксированной информацией, жестко закодированной в коде разметки. Вместо этого все необходимые объекты TreeViewItem либо создаются программно, либо отображаются в виде коллекции с помощью привязки данных.

В заполнении элемента управления TreeView данными нет ничего сложного: как и в случае любого элемента ItemsControl, для этого требуется просто установить свойство ItemsSource. Однако при таком подходе данными заполняется только первый уровень TreeView. Более интересный подход предусматривает применение в TreeView иерархических данных, имеющих нечто вроде вложенной структуры.

Например, рассмотрим элемент управления TreeView, показанный ниже. Первый уровень состоит из объектов Category, в то время как второй уровень отображает подпадающие под каждую из этих категорий объекты Product.

Элемент управления TreeView позволяет легко отображать иерархические данные независимо от того, используются ли созданные вручную классы или ADO.NET-объекты DataSet. Главное — указать правильные шаблоны данных, разъясняющие отношения между различными уровнями данных.

Изначально коллекция Category привязывается к дереву для того, чтобы она отображалась на первом уровне:

trw_Products.ItemsSource = App.StoreDb.GetCategoriesAndProducts();

Для отображения категорий необходимо предоставить шаблон TreeView.ItemTemplate, способный обрабатывать привязанные объекты. В данном примере требуется отобразить свойство CategoryName каждого объекта Category. Ниже показан шаблон данных, который делает это:

<TreeView Name="trw_Products" Margin="5">
      <TreeView.ItemTemplate>
             <HierarchicalDataTemplate ItemsSource="{Binding Path=Products}">
                        <TextBlock Text="{Binding Path=CategoryName}"/>
                        <HierarchicalDataTemplate.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Path=ModelName}"></TextBlock>
                            </DataTemplate>
                        </HierarchicalDataTemplate.ItemTemplate>
             </HierarchicalDataTemplate>
      </TreeView.ItemTemplate>
</TreeView>

Единственная необычная деталь здесь — то, что TreeView.ItemTemplate устанавливается не с помощью объекта DataTemplate, а с помощью объекта HierarchicalDataTemplate. У объекта HierarchicalDataTemplate имеется одно дополнительное преимущество: он может упаковывать второй шаблон, а затем, соответственно, извлекать коллекцию элементов из первого уровня и передавать их шаблону второго уровня. Все, что требуется — это установить свойство ItemsSource, чтобы оно указывало на свойство, имеющее дочерние элементы, а свойство ItemTemplate — чтобы оно указывало, как должен форматироваться каждый объект.

Элемент TreeView
Пройди тесты
Лучший чат для C# программистов