Чтобы отобразить данные из файла XML в TreeView, данные будут организованы в модели данных, что делает его манипуляции и представление через TreeView легко.
1. Модель данных
Каждая запись в дереве будет получать от общего базового типа.
public abstract class NamedTreeEntry
{
public string DisplayName { get; set; }
}
Поскольку все элементы должны отображаться имя, соответствующее свойство отображаемое_имя также объявленный в базовом типе.
Для нашего случая необходимо учитывать два конкретных типа, основанных на этом базовом типе: каталоги и файлы.
public class FileEntry : NamedTreeEntry
{
// ... and other file-specific public properties and methods
}
public class DirectoryEntry : NamedTreeEntry
{
public ObservableCollection<NamedTreeEntry> ChildEntries
{
get { return _collChildren; }
}
private readonly ObservableCollection<NamedTreeEntry> _collChildren;
public DirectoryEntry(IEnumerable<NamedTreeEntry> childEntries)
{
_collChildren = (childEntries != null) ?
new ObservableCollection<NamedTreeEntry>(childEntries)
: new ObservableCollection<NamedTreeEntry>();
}
// ... and other directory-specific public properties and methods
}
Обратите внимание на использование типа ObservableCollection<T> для списка детей. Хотя это не является строго необходимым для примера, описанного здесь, ObservableCollection < T> позволяет динамически добавлять или удалять дочерние элементы, в то время как элемент управления TreeView постоянно обновляется.
2. Преобразование XML в модель данных
чтения и преобразования данных XML в модель данных с использованием типов, введенных выше, может быть довольно простым. Использование Linq (в сочетании с XDocument/XElement), требуемый код только несколько строк:
public DirectoryEntry CreateDataModelFromXml(Stream xmlFileStream)
{
XDocument xDoc = XDocument.Load(xmlFileStream);
return new DirectoryEntry(QueryChildEntries(xDoc.Element("Folder")))
{
Name = "ROOT"
};
}
private IEnumerable<NamedTreeEntry> QueryChildEntries(XElement xElem)
{
return
from childElem in xElem.Elements()
where childElem.Name == "dir" || childElem.Name == "file"
select (childElem.Name == "file") ?
(NamedTreeEntry) new FileEntry()
{
Name = childElem.Element("name").Value
}
: new DirectoryEntry(QueryChildEntries(childElem))
{
Name = childElem.Element("name").Value,
};
}
Для удобочитаемости, любой вид обработки исключений и здравомыслие проверки были опущены. В вашем реальном коде эти вещи ДОЛЖНЫ выполняться. Приведенный примерный код может вести себя смешно, если его кормят некорректными/неверными данными XML.
(Данный пример кода предполагает < режа> < файла> элементы являются дочерними < папок> узла. Однако в вашем XML, < каталога>, < файла> дети элемента в < FolderName>, который выглядит как ошибка. Если это действительно преднамеренно, вам нужно будет принять примерный код соответственно.)
В соответствующем месте в исходном коде, просто вызовите:
DirectoryEntry rootEntry;
using (FileStream stream = new FileStream(xmlFilePathString, FileMode.Open, FileAccess.Read))
{
rootEntry = CreateDataModelFromXml(stream);
}
3. TreeView
Теперь вам нужно только назначить коллекцию верхнего уровня записи в элемент управления TreeView (который в этом примере называется MyTreeView).
MyTreeView.ItemsSource = rootEntry.ChildEntries;
Если вы хотите, чтобы отобразить корневую запись в виде дерева, сделать что-то вроде следующего:
MyTreeView.ItemsSource = new DirectoryEntry[] { rootEntry };
В вашем реальном коде, вы, вероятно, использовать привязку данных в XAML вместо настройки ItemsSource Недвижимость в кодовом замке.
Ну, с тем, что мы сделали до сих пор, элемент управления TreeView покажет только записи на первом уровне. Но он не будет показывать дочерние записи, просто потому, что он не знает о них. Время введения HierarchicalDataTemplate. HierarchicalDataTemplate не только определяет внешний вид записи, но также имеет параметр для привязки к коллекции с дочерними элементами.
Для записи каталога, то HierarchicalDataTemplate может выглядеть следующим образом:
<HierarchicalDataTemplate DataType="{x:Type My:DirectoryEntry}" ItemsSource="{Binding ChildEntries}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Dir: " />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
Обратите внимание на DataType шаблона, а ItemsSource параметр, который связывается с ChildEntries DirectoryEntry в собственность с коллекцией дочерние записи.
Для записей в файлах DataTemplate достаточно, так как у них нет детей.
<DataTemplate DataType="{x:Type My:FileEntry}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="File: " />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
Теперь элемент управления TreeView должен знать только, какой из этих двух шаблонов должен использоваться для записи. Для многих случаев использование элемента управления TreeView делает это очень простым - просто добавьте эти два шаблона в локальный ресурсный словарь управления TreeView. TreeView выберет первый шаблон данных (HierarchicalDataTemplate - также шаблон данных) из своего словаря ресурсов, тип данных которого соответствует типу соответствующей записи.
В общем, полный XAML для TreeView будет выглядеть следующим образом:
<TreeView Name="MyTreeView">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type My:DirectoryEntry}" ItemsSource="{Binding ChildEntries}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Dir: " />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type My:FileEntry}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="File: " />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</TreeView.Resources>
</TreeView>
(В тех случаях, когда выбор шаблона по типу данных не представляется возможным, ItemTemplateSelector может быть использован вместо.)
Вы уже читали XML-файл в какой-либо структуре данных (если да, то пожалуйста, покажите код)? Или, читаете ли XML-файл свою актуальную проблему? – elgonzo
@elgonzo Чтение XML-файла - моя фактическая проблема. – user2330678
Хорошо, еще несколько вопросов :) Вам нужна информация из файла XML только для вашего TreeView, или вам нужны данные XML также где-то еще в вашем программном обеспечении?Отображает ли TreeView только текст из XML или XML содержит некоторые атрибуты/элементы, которые влияют на визуализацию TreeViewItems? – elgonzo