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

时间:2011-06-20 17:24:05

标签: c# wpf treeview code-behind

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

2 个答案:

答案 0 :(得分:58)

我被这个问题所吸引,并把它扔到了一起。作为第一关,我认为我非常接近你正在寻找的东西。谈论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:您需要将硬编码路径设置为系统上有意义的路径。

以下是显示不同级别的目录和文件的屏幕截图...

enter image description here

答案 1 :(得分:3)

以前解决方案的小扩展: 我添加了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>