从 wpf 中的文件路径列表填充树视图

Posted

技术标签:

【中文标题】从 wpf 中的文件路径列表填充树视图【英文标题】:populate treeview from list of file paths in wpf 【发布时间】:2011-09-18 21:24:57 【问题描述】:

有几个示例说明如何从文件路径集合中填充树视图,例如 this 或 this other 示例。我似乎无法为 WPF 找到这样的示例。我知道我可以集成 Windows 窗体并使用不同的控件以使其工作,但如果我可以使用 wpf 树视图控件做同样的事情,那就太好了。我要构建的树视图由大约 50,000 个文件组成,因此我认为将它绑定到某些东西会更好。但首先在绑定它之前,我认为基于字符串列表(字符串包含文件的路径)构造一个会很有帮助。

【问题讨论】:

您不必先填充整个集合。您可以按需获取树控件。我为此使用了 Teleriks 树控件。 【参考方案1】:

我对这个问题很感兴趣并把它放在一起。作为第一次通过,我认为我非常接近您正在寻找的内容。不过,谈论 50,000 个项目让我认为延迟加载可能是合适的。无论如何,这是基于 Josh Smith 的 article 的简单版本。我把所有的代码都放在这里了,但神奇的是数据模板。

给定几个类来表示我们正在使用的对象...

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:您需要将硬编码路径设置为对您的系统有意义的内容。

这是一个屏幕截图,显示了不同级别的目录和文件...

【讨论】:

乔恩非常感谢!你的答案看起来很棒。我期待着明天早上回来时测试您的解决方案。不要再编辑了……让我先测试一下。 这是一个很好的答案。但是,无需创建 Item 和 FileItem 类。您可以为 System.IO DirectoryInfo 和 FileInfo 类创建本地 DataTemplate。 现在增强它以使用延迟加载:] TreeView 的 ItemSource 是如何知道它的 Binding 的? @Thomas 窗口构造函数中的DataContext = items 赋值设置了数据上下文 - 没有路径的BindingDataContext,即items【参考方案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>

【讨论】:

以上是关于从 wpf 中的文件路径列表填充树视图的主要内容,如果未能解决你的问题,请参考以下文章

试图用数组文本填充列表视图

从路径列表中表示文件系统(文件/目录)的 Java 树

从列表 os 文件路径 (Python) 构造树 - 取决于性能

从文件路径构建树

如何使用c#从google驱动器api获取文件夹的完整路径

WPF从共享项目访问图像路径