通过递归搜索HierarchicalData [英] Search through HierarchicalData with recursion

查看:73
本文介绍了通过递归搜索HierarchicalData的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用ScanItem列表构建树状视图.实际上,ScanItem的类是:

public class ScanItem
    {
        public string FullPath { get; set; }
        public string Name
        {
            get
            {
                return Path.GetFileName(FullPath);
            }

        }
        public DateTime ModifiedDate { get; set; }
        public DateTime CreatedDate { get; set; }
        public FileAttributes Attributes { get; set; }
        public bool IsDirectory { get; set; }


        public string Extension
        {
            get
            {
                if (IsDirectory)
                    return "Folder";
                else
                    return Path.GetExtension(Name);
            }
        }

        public UInt64 Size { get; set; }            
    }

为了创建树视图,我需要创建另外两个类以区分树视图中的文件夹和文件:

    public class ScanFile : ScanItem
    {

    }
    public class ScanDir : ScanItem 
    {
        public List<ScanItem> Items { get; set; }
        public ScanDir()
        {
            Items = new List<ScanItem>();
        }                
    }

请注意,ScanFile类与ScanItem类似,而ScanDir类具有一个名为Items的额外属性,并将包含其自身的项目列表.

因此,如果我要遍历这个双向目录(C:\ Temp):

我的列表实际上包含:

请注意,如果我扩展一个ScanDir对象,我将获得另一个List:

为了填充以下树视图:

因此,我可以通过在特定路径中搜索文件和目录来使用递归填充此列表.

我只想解释一下我的情况,因为互联网上有几个地方可以过滤树状视图,而这正是我真正想要做的.但是,如果我可以遍历列表中的每个项目,然后在不满足某些条件的情况下将其删除,那将是很好的选择:

我实际上已经尝试使用以下递归方法来过滤我的结果.

public List<ScanItem> search(List<ScanItem> items)
    {
        var filter = new List<ScanItem>();

        foreach (var item in items)
        {
            if (!item.FullPath.Contains("stringIwantToLookFor")) continue;
            filter.Add(item);
            if (item.IsDirectory)
            {
                search(((ScanDir)item).Items);                    
            }                
        }

        return filter;
    }

我认为,如果找到一个项目,则需要添加所有父根目录,这就是为什么它不起作用的原因.之所以要构建自己的递归方法,是因为我希望能够基于特殊的条件来过滤树形视图.

换句话说,如果我要在列表视图中包含所有包含"X.txt"的项目,我只想看一下:

解决方案

我会这样做:在您的ScanItem上创建public abstract ScanItem Seach(string s).然后,您可以使用要搜索的字符串来调用它.

实际实现如下:

ScanFile:

public override ScanItem Seach(string s)
{
    if (Name.Contains(s))
        return this;

    return null;
}

ScanDir:

public override ScanItem Seach(string s)
{
    var results = Items.Select(i => i.Seach(s)).Where(i => i != null).ToList();
    if (results.Any())
    {
        var result = (ScanDir)MemberwiseClone();
        result.Items = results;
        return result;
    }

    return null;
}

ScanFile中的实现很简单:如果文件匹配,则返回它,否则返回null.在ScanDir中,递归地在所有子项上调用Search.如果它们中的任何一个返回非null,请创建当前对象的副本,并将副本的Items仅设置为匹配的对象.如果没有匹配项,则返回null.

请注意,这只会搜索文件名,而不搜索目录.但是,如果您要这样做,那么这样的修改将很简单.

I am building a treeview with a list of ScanItem. The class of ScanItem is actually:

public class ScanItem
    {
        public string FullPath { get; set; }
        public string Name
        {
            get
            {
                return Path.GetFileName(FullPath);
            }

        }
        public DateTime ModifiedDate { get; set; }
        public DateTime CreatedDate { get; set; }
        public FileAttributes Attributes { get; set; }
        public bool IsDirectory { get; set; }


        public string Extension
        {
            get
            {
                if (IsDirectory)
                    return "Folder";
                else
                    return Path.GetExtension(Name);
            }
        }

        public UInt64 Size { get; set; }            
    }

In order for me to create a treeview I needed to create two other classes in order to distinguish the folders and files in my treeview:

    public class ScanFile : ScanItem
    {

    }
    public class ScanDir : ScanItem 
    {
        public List<ScanItem> Items { get; set; }
        public ScanDir()
        {
            Items = new List<ScanItem>();
        }                
    }

Note that the class ScanFile is just like the ScanItem and the ScanDir class has an extra property called Items and will contain a list of items of itself.

So if I where to iterate through this direcotory (C:\Temp):

my List will actually contain:

note that if I expand one ScanDir object I will get another List:

in order to populate the following treeview:

So I was able to populate this list using recursion by searching for files and directories in a specific path.

I just wanted to explain my situation because there are several places in the internet that enable you to filter a treeview and that is what I actually want to do. But it will be nice if I can iterate through each item in List and then remove it if some criteria is not met:

I have actually tried using the following recursive method to filter my results.

public List<ScanItem> search(List<ScanItem> items)
    {
        var filter = new List<ScanItem>();

        foreach (var item in items)
        {
            if (!item.FullPath.Contains("stringIwantToLookFor")) continue;
            filter.Add(item);
            if (item.IsDirectory)
            {
                search(((ScanDir)item).Items);                    
            }                
        }

        return filter;
    }

I think that if an item is found I need to add all the parent root directories and that's why it does not work. The reason why I want to build my own recursion method is because I want to be able to filter the treeview based on spesific criteria.

EDIT:

In other words if I want to have all the items that contain "X.txt" in my listview I want to just see:

解决方案

I would do it like this: create public abstract ScanItem Seach(string s) on your ScanItem. You can then call it with the string you want to search for.

The actual implementation would look like this:

ScanFile:

public override ScanItem Seach(string s)
{
    if (Name.Contains(s))
        return this;

    return null;
}

ScanDir:

public override ScanItem Seach(string s)
{
    var results = Items.Select(i => i.Seach(s)).Where(i => i != null).ToList();
    if (results.Any())
    {
        var result = (ScanDir)MemberwiseClone();
        result.Items = results;
        return result;
    }

    return null;
}

The implementation in ScanFile is easy: if the file matches, return it, else return null. In ScanDir, call Search on all child items recursively. If any of them returned non-null, create a copy of the current object and set the Items of the copy only to those that matched. If none matched, return null.

Note that this will search only through the names of files, not directories. But if you want to do that, such modification is going to be straight-forward.

这篇关于通过递归搜索HierarchicalData的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆