通过递归搜索HierarchicalData [英] Search through HierarchicalData with recursion
问题描述
我正在用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屋!