Существует несколько примеров того, как заполнить древовидное представление из набора путей файлов, таких как this или этот другой. Я не могу найти такой пример для WPF. Я знаю, что могу интегрировать формы окон и использовать другой элемент управления, чтобы он работал, но будет хорошо, если я смогу сделать то же самое с элементом управления wpf treeview. Древовидное представление, которое я хочу построить, состоит из около 50 000 файлов, поэтому я думаю, что будет лучше, если он привяжет его к чему-то. Но прежде, чем привязать его, я думаю, что будет полезно построить его на основе списка строк (строки содержат пути к файлам).
Заполнять дерево из списка путей файла в wpf
Ответ 1
Я был заинтригован вопросом и бросил это вместе. В качестве первого прохода я думаю, что я довольно близок к тому, что вы ищете. Говоря о 50 000 предметов, я думаю, что ленивая загрузка может быть уместной. Во всяком случае, вот простая версия, основанная на статье статьи Джоша Смита. Я поместил весь код здесь, но волшебство действительно имеет место с шаблонами данных.
Учитывая несколько классов для представления объектов, с которыми мы работаем...
using System.Collections.Generic;
namespace WpfTreeViewBinding.Model
{
public class Item
{
public string Name { get; set; }
public string Path { get; set; }
}
}
и...
namespace WpfTreeViewBinding.Model
{
public class FileItem : Item
{
}
}
и...
namespace WpfTreeViewBinding.Model
{
public class DirectoryItem : Item
{
public List<Item> Items { get; set; }
public DirectoryItem()
{
Items = new List<Item>();
}
}
}
Я создал рекурсивный метод для загрузки некоторых каталогов/файлов...
using System.Collections.Generic;
using System.IO;
using WpfTreeViewBinding.Model;
namespace WpfTreeViewBinding
{
public class ItemProvider
{
public List<Item> GetItems(string path)
{
var items = new List<Item>();
var dirInfo = new DirectoryInfo(path);
foreach(var directory in dirInfo.GetDirectories())
{
var item = new DirectoryItem
{
Name = directory.Name,
Path = directory.FullName,
Items = GetItems(directory.FullName)
};
items.Add(item);
}
foreach(var file in dirInfo.GetFiles())
{
var item = new FileItem
{
Name = file.Name,
Path = file.FullName
};
items.Add(item);
}
return items;
}
}
}
Оттуда это просто вопрос получения данных...
using System.Windows;
namespace WpfTreeViewBinding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var itemProvider = new ItemProvider();
var items = itemProvider.GetItems("C:\\Temp");
DataContext = items;
}
}
}
И отображение его...
<Window x:Class="WpfTreeViewBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Model="clr-namespace:WpfTreeViewBinding.Model"
Title="MainWindow"
Height="350" Width="525">
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type Model:DirectoryItem}"
ItemsSource="{Binding Items}">
<TextBlock Text="{Binding Path=Name}" ToolTip="{Binding Path=Path}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type Model:FileItem}">
<TextBlock Text="{Binding Path=Name}" ToolTip="{Binding Path=Path}" />
</DataTemplate>
</Window.Resources>
<Grid Margin="8">
<TreeView ItemsSource="{Binding}" />
</Grid>
</Window>
Вся магия действительно происходит с шаблонами данных. Я думаю, что ключом к этому является использование HierarchicalDataTemplate для любых элементов с иерархией (например, каталогов).
ПРИМЕЧАНИЕ 1: Я не тестировал это широко. Он не был профилирован для работы. Я бы приветствовал любую обратную связь, хотя, поскольку это проблема, которую я давно пытался решить и сдался. Спасибо!
ПРИМЕЧАНИЕ 2. Вам необходимо установить жестко закодированный путь к чему-то, что имеет смысл в вашей системе.
Вот скриншот, показывающий каталоги и файлы на разных уровнях...
Ответ 2
Малое расширение для предыдущего решения: Я добавил код xaml для поддержки значков и поддержку переключения между значками для открытой и закрытой папки:
<HierarchicalDataTemplate DataType="{x:Type viewModels:SourceControlDirecoryViewModel}"
ItemsSource="{Binding Items}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Width="16"
Height="16"
Source="{StaticResource ImageSourceFolderClosed16x16}"
x:Name="img" />
<TextBlock Text="{Binding Path=Name}"
ToolTip="{Binding Path=Path}"
Grid.Column="2" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsExpanded, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TreeViewItem}}}"
Value="True">
<Setter Property="Source"
TargetName="img"
Value="{StaticResource ImageSourceFolderOpened16x16}" />
</DataTrigger>
</DataTemplate.Triggers>
</HierarchicalDataTemplate>
Ответ 3
Пожалуйста. Я заявлен в WPF, и я хотел бы знать, как вы определили путь для этих изображений: ImageSourceFolderClosed16x16 и ImageSourceFolderOpened16x16. Также вы меняете исходный тип данных HierarchicalDataTemplate с "{x: Type Model: DirectoryItem}" на этот: "{x: Type viewModels: SourceControlDirecoryViewModel}". Итак, вы изменили оригинальный класс? Возможно ли, вы предоставите мне полный XAML и новый класс?
Спасибо.