TreeView, ObjectDataProvider, HierarchicalDataTemplate, xsd2Code ничего не показывает
У меня есть иерархия объектов, созданная с помощью xsd2code. Иерархия объектов состоит из корневого объекта типа Project, который содержит ObservableCollection именованной папки Folder, которая является рекурсивным объектом, содержащим ObservableCollection именованной папки Folder и именованного файла File. Я хочу связать эту иерархию объектов с TreeView через ObjectDataProvider и управлять отображать через определения HierarchicalDataTemplate
ObjectDataProvider и DataTemplates определяются в ресурсе, объединенном в App.xaml следующим образом
<HierarchicalDataTemplate x:Key="projectTemplate"
DataType="{x:Type model:Project}"
ItemsSource="{Binding Path=folder}"
>
<Grid ToolTip="{Binding Path=Name}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="Images/folder_documents_512.ico" Grid.Column="0"/>
<TextBlock Grid.Column="1" Margin="6,0,0,0"
Text="{Binding Path=Name}"
/>
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
DataType="{x:Type model:Folder}"
ItemsSource="{Binding Path=file}">
<Grid ToolTip="{Binding Path=name}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="Images/folder_vectors_512.ico" Grid.Column="0"/>
<TextBlock Grid.Column="1" Margin="6,0,0,0"
Text="{Binding Path=name}"
/>
</Grid>
</HierarchicalDataTemplate>
<DataTemplate
DataType="{x:Type model:File}">
<Grid ToolTip="{Binding Path=name}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="Images/article-24.png" Grid.Column="0"/>
<TextBlock Grid.Column="1" Margin="6,0,0,0"
Text="{Binding Path=name}"
/>
</Grid>
</DataTemplate>
<ObjectDataProvider
x:Key="project"
>
</ObjectDataProvider>
TreeView определяется так
<TreeView x:Name="tvProject"
ItemsSource="{Binding Source={StaticResource project}}"
>
Глобальная обработка такова: я загружаю иерархию объектов из файла XML (функциональность xsd2code). Как я вижу в отладке, моя иерархия объектов чиста. Затем я связываю иерархию объектов с ObjectDataProvider в коде, как это
ObjectDataProvider dp = Application.Current.FindResource("project") as ObjectDataProvider;
dp.ObjectInstance = _project;
Ну, ничего не появляется в TreeView. Что мне не хватает?
1 ответ
Я решил свою проблему,
Во-первых, мне пришлось привязать коллекцию к ObjectDataProvider, а не просто к одному объекту. Я не думаю, что это требование ObjectDataProvider, а скорее требование для HierarchicalDataTemplate.
ObjectDataProvider dp = Application.Current.FindResource("project") as ObjectDataProvider;
ArrayList ocp = new ArrayList();
ocp.Add(_project);
dp.ObjectInstance = ocp;
Затем мне пришлось связать ссылку на различные DataTemplates через свойство ItemTemplate, например:
Сначала на TreeView
<TreeView x:Name="tvProject"
ItemsSource="{Binding Source={StaticResource project}}"
ItemTemplate="{StaticResource projectTemplate}"
>
А потом в другой DataTemplate
<DataTemplate x:Key="fileTemplate"
DataType="{x:Type model:File}">
<Grid ToolTip="{Binding Path=name}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="Images/article-24.png" Grid.Column="0"/>
<TextBlock Grid.Column="1" Margin="6,0,0,0"
Text="{Binding Path=name}"
/>
</Grid>
</DataTemplate>
<HierarchicalDataTemplate x:Key="folderTemplate"
DataType="{x:Type model:Folder}"
ItemsSource="{Binding Path=file}"
ItemTemplate="{StaticResource fileTemplate}">
<Grid ToolTip="{Binding Path=name}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="Images/folder_vectors_512.ico" Grid.Column="0"/>
<TextBlock Grid.Column="1" Margin="6,0,0,0"
Text="{Binding Path=name}"
/>
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="projectTemplate"
DataType="{x:Type model:Project}"
ItemsSource="{Binding Path=folder}"
ItemTemplate="{StaticResource folderTemplate}"
>
<Grid ToolTip="{Binding Path=Name}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="Images/folder_documents_512.ico" Grid.Column="0"/>
<TextBlock Grid.Column="1" Margin="6,0,0,0"
Text="{Binding Path=Name}"
/>
</Grid>
</HierarchicalDataTemplate>
Теперь работает
РЕДАКТИРОВАТЬ
Поскольку коллекция может возвращать различные типы (например, папка и файл), вам нужен селектор шаблонов
public class FileSystemObjectTemplateSelector : DataTemplateSelector
{
public override DataTemplate
SelectTemplate(object item, DependencyObject container)
{
FrameworkElement element = container as FrameworkElement;
if (element != null && item != null && item is FileSystemObject)
{
if (item is File)
return Application.Current.FindResource("fileTemplate") as DataTemplate;
if (item is Folder)
return Application.Current.FindResource("folderTemplate") as DataTemplate;
}
return null;
}
}
и позвоните в XAML
<local:FileSystemObjectTemplateSelector x:Key="FileSystemObjectTemplateSelector" />
<HierarchicalDataTemplate x:Key="folderTemplate"
DataType="{x:Type model:Folder}"
ItemsSource="{Binding Path=fsObjects, Converter={StaticResource SortFoldersAndFiles}}"
ItemTemplateSelector="{StaticResource FileSystemObjectTemplateSelector}" >
</HierarchicalDataTemplate>