Подтвердить что ты не робот

Заполнять дерево из списка путей файла в wpf

Существует несколько примеров того, как заполнить древовидное представление из набора путей файлов, таких как this или этот другой. Я не могу найти такой пример для WPF. Я знаю, что могу интегрировать формы окон и использовать другой элемент управления, чтобы он работал, но будет хорошо, если я смогу сделать то же самое с элементом управления wpf treeview. Древовидное представление, которое я хочу построить, состоит из около 50 000 файлов, поэтому я думаю, что будет лучше, если он привяжет его к чему-то. Но прежде, чем привязать его, я думаю, что будет полезно построить его на основе списка строк (строки содержат пути к файлам).

4b9b3361

Ответ 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. Вам необходимо установить жестко закодированный путь к чему-то, что имеет смысл в вашей системе.

Вот скриншот, показывающий каталоги и файлы на разных уровнях...

enter image description here

Ответ 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 и новый класс?

Спасибо.