【问题标题】:Form a tree of files and folders形成文件和文件夹树
【发布时间】:2015-03-29 12:21:41
【问题描述】:

如何递归地从文件夹中获取所有文件夹和文件树?我需要将这棵树放入 DataTable 并从中形成一个 treeView。我在形成递归方法方面有点问题,现在我只有一个不能正常工作的草稿:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private int id, parentID;
        private List<TREE> tree;
        public MainWindow()
        {
            InitializeComponent();

            tree = new List<TREE>();
            id = 0;
            parentID = 0;

            fill(@"D:\c#");
        }

        private List<TREE> fill(string path)
        {
            DirectoryInfo dir = new DirectoryInfo(path);
            foreach (DirectoryInfo folder in dir.GetDirectories())
            {
                tree.Add(new TREE(){ID = id++, ParentID = parentID++, Name = folder.Name, Type = "Folder"});

                foreach (FileInfo file in folder.GetFiles())
                {
                    tree.Add(new TREE() { ID = id, ParentID = parentID, Name = file.Name, Type = "File" });  
                }
                var p = folder.GetDirectories();
                if (p.Length > 0)
                {
                    dir = folder;
                    fill(dir.FullName);
                }
            }
            return tree;
        }
    }

public class TREE
{
    public int ID { get; set; }
    public int ParentID {get;set;}
    public string Name {get;set;}
    public string Type {get;set;}
}

}

拜托,你能告诉我形成树并将树放入 DataTable 的正确方法吗?列表很好,但我需要数据表。

我试过这个,但它不想正常工作:

public DataTable fill(DirectoryInfo dir)
        {
            DataTable dt = new DataTable("Tasks");

            //dt.Columns.Add("ID");
            dt.Columns.Add("ParentID");
            dt.Columns.Add("Name");
            dt.Columns.Add("Type");

            foreach (var folder in dir.GetDirectories())
            {
                var row = dt.NewRow();

                row["ParentID"] = folder.Parent;
                row["Name"] = folder.Name;
                row["Type"] = "dir";
                dt.Rows.Add(row);

                foreach (var file in folder.GetFiles())
                {
                    var row2 = dt.NewRow();

                    row["ParentID"] = folder.Parent;
                    row["Name"] = file.Name;
                    row["Type"] = "file";
                    dt.Rows.Add(row2);
                }

                fill(folder);
            }
            return dt;
        }

【问题讨论】:

标签: c# recursion datatable tree treeview


【解决方案1】:

以下是我如何实现递归部分:

static class IdGenerator
{
    static int _id = 1;
    public static int Generate() { return _id++; }
}

class Tree
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }
    public Tree Parent { get; set; }
    public virtual ICollection<string> Files { get; set; }
    public virtual ICollection<Tree> Trees { get; set; }

    internal Tree ()
    {
        Id = IdGenerator.Generate();
        Name = String.Empty;
        ParentId = 0;
        Parent = null;
        Files = new List<string>();
        Trees = new List<Tree>();
    }

    public override string ToString()
    {
        return String.Join("\n", new[] { Id + "\t" + Path.Combine(Parent != null ? Parent.Name : String.Empty, Name) }.Union(Files).Union(Trees.Select(t => t.ToString()))) + "\n";
    }

    public static Tree CreateTree(string path, Tree parent, string pattern)
    {
        try
        {
            var tree = new Tree
            {
                Parent = parent,
                ParentId = parent != null ? parent.Id : 0,
                Name = Path.GetFileName(path),
                Files = Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly).Select(f => Path.GetFileName(f)).ToArray(),
            };
            tree.Trees = Directory.GetDirectories(path, "*.*", SearchOption.TopDirectoryOnly).Select(d => CreateTree(d, tree, pattern)).ToArray();

            return tree;
        }
        catch (UnauthorizedAccessException)
        { return new Tree(); }
    }
}

如果我要继续这样做,我会使用 Entity Framework Code First 从 POCO Tree 生成数据库,并删除静态 IdGenerator,因为 EF 会为我生成这些数据库 ID。

编辑

但是,以下是在 DataTable 中执行此操作的方法:

class TreeDataTable : DataTable
{
    public TreeDataTable()
        : this("trees")
    {
    }

    public TreeDataTable(string tableName)
        : base(tableName)
    {
        Columns.Add("Id");
        Columns.Add("Name");
        Columns.Add("ParentId");
        Columns.Add("Type");
    }

    public void AddFile(int id, string name, int parent)
    {
        AddRow(id, name, parent, typeof(FileInfo));
    }

    public void AddTree(Tree tree)
    {
        AddRow(tree.Id, tree.Name, tree.ParentId, typeof(DirectoryInfo));
        var table = tree.ToDataTable();
        foreach (var r in table.Rows.Cast<DataRow>())
            AddRow(Convert.ToInt32(r["Id"]), r["Name"].ToString(), Convert.ToInt32(r["ParentId"]), Type.GetType(r["Type"].ToString()));
    }

    public string ToXml()
    {
        using (var sw = new StringWriter())
        {
            using (var tw = new XmlTextWriter(sw))
            {
                tw.Formatting = Formatting.Indented;

                tw.WriteStartDocument();
                tw.WriteStartElement(TableName);

                ((IXmlSerializable)this).WriteXml(tw);

                tw.WriteEndElement();
                tw.WriteEndDocument();

            }

            return sw.ToString();
        }
    }

    private void AddRow(int id, string name, int parent, Type type)
    {
        var row = NewRow();
        row["Id"] = id;
        row["Name"] = name;
        row["ParentId"] = parent;
        row["Type"] = type.ToString();

        Rows.Add(row);
    }
}

并将此方法添加到Tree:

    public DataTable ToDataTable()
    {
        var table = new TreeDataTable();

        foreach (var f in Files)
            table.AddFile(IdGenerator.Generate(), f, Id);
        foreach (var t in Trees)
            table.AddTree(t);

        return table;
    }

使用方法如下:

class Program
{
    static void Main(string[] args)
    {
        var path = args.FirstOrDefault(a => !String.IsNullOrEmpty(a)) ?? @"C:\Documents\Videos";
        args = args.Skip(1).ToArray();
        var pattern = args.FirstOrDefault(a => !String.IsNullOrEmpty(a)) ?? "*.mp4";
        var tree = Tree.CreateTree(path, null, pattern);

        Console.WriteLine((tree.ToDataTable() as TreeDataTable).ToXml());
    }
}

【讨论】:

  • 谢谢,我会尽力理解这一点。但是,我想要这样简单的 [问题已更新]。
  • 您的问题是“如何递归地从文件夹中获取所有文件夹和文件树?”和“我在形成递归方法方面有一点问题”。这回答了这个问题。
  • 我知道,但是做一个简单的任务太难了,没有冒犯。
  • 非常感谢,我就用这个作为dll。
  • 如何将此DataTable绑定到WPF中的TreeView项?
猜你喜欢
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多