使用 LINQ 筛选 DirectoryInfo 的 ObservableCollection
Filter an ObservableCollection of DirectoryInfo with LINQ
我正在使用 MVVM 使用 DirectoryInfo 及其所有子目录和文件填充 TreeView。
然后我想使用 LINQ .where() 搜索树视图,但我只搜索顶级目录而不是文件。
我正在使用递归方法创建 treeview/DirectoryInfo:
public class ItemProvider
{
public ObservableCollection<Item> GetItems(string path)
{
var items = new ObservableCollection<Item>();
if (System.IO.Directory.Exists(path))
{
var dirInfo = new DirectoryInfo(path);
foreach (var directory in dirInfo.EnumerateDirectories())
{
var item = new DirectoryItem
{
Name = directory.Name,
Path = directory.FullName,
Items = GetItems(directory.FullName)
};
items.Add(item);
}
foreach (var file in dirInfo.EnumerateFiles())
{
InteropBitmap thumbImg = ShellFile.FromFilePath(file.FullName).Thumbnail.BitmapSource as InteropBitmap;
thumbImg.Freeze();
var item = new FamilyItem
{
Name = file.Name,
Path = file.FullName,
FamImage = thumbImg
};
if (item.Name.Contains(".rfa"))
{
items.Add(item);
}
}
return items;
}
else
{
return items;
}
}
DirectoryItem 和 FamilyItem 都继承了一个名为 Item:
的模型
商品型号:
public class Item
{
public string Name { get; set; }
public string Path { get; set; }
public InteropBitmap FamImage { get; set; }
}
DirectoryItem 模型:
public class DirectoryItem : Item
{
public ObservableCollection<Item> Items { get; set; }
public DirectoryItem()
{
Items = new ObservableCollection<Item>();
}
}
家庭项目:
public class FamilyItem : Item
{
}
我正在过滤集合:
Items = new ObservableCollection<Item>(ItemsCache.Where(x => x.Name.ToLower().Contains(SearchText.ToLower())));
我只得到匹配的顶级目录 - 我想得到所有匹配的“结束”文件 - 我该怎么做?
好的,修改答案。
您必须将您的 collection 正手压平(或将其压平)。
public ObservableCollection<Item> GetItemsFlat(string path)
{
var items = new ObservableCollection<Item>();
if (!System.IO.Directory.Exists(path))
return items;
var dirInfo = new DirectoryInfo(path);
foreach (var directory in dirInfo.EnumerateDirectories())
{
var item = new DirectoryItem
{
Name = directory.Name,
Path = directory.FullName,
Items = GetItems(directory.FullName)
};
items.Add(item);
foreach (var item in GetItemsFlat(directory.FullName))
items.Add(item);
}
foreach (var file in dirInfo.EnumerateFiles("*.rfa"))
{
InteropBitmap thumbImg = ShellFile.FromFilePath(file.FullName).Thumbnail.BitmapSource as InteropBitmap;
thumbImg.Freeze();
var item = new FamilyItem
{
Name = file.Name,
Path = file.FullName,
FamImage = thumbImg
};
items.Add(item)
}
}
使用 Path
(即全名)属性 进行过滤,将文件包含在匹配的子目录中,即。
ItemsCache.Where(x => x.Path.ToLower().Contains(SearchText.ToLower()))
还重构您的代码以使用“return 及早”策略。 (https://dev.to/jpswade/return-early-12o5)
即。代替
if (System.IO.Directory.Exists(path)) { ...lots of code }
做
if (!System.IO.Directory.Exists(path)) return EmptyCollection;`
...lots of code
您还可以改进此代码以丢弃 collection 中的 'empty' 目录子树。
同时检查 GetFileSystemInfo
https://docs.microsoft.com/en-us/dotnet/api/system.io.directoryinfo.getfilesysteminfos?view=net-6.0 可用于搜索包括子目录的文件
您可以通过递归版本覆盖 .Where(..)
:
public static class ExtenstioMethods
{
public static IEnumerable<Item> Where<Item>(this IEnumerable<Item> source, Func<Item, bool> predicate)
{
var result = new List<Item>();
foreach (var item in source)
{
if ((item is FamilyItem) && predicate(item))
{
result.Add(item);
}
else if (item is DirectoryItem)
{
var newSourc = ((item as DirectoryItem).Items) as IEnumerable<Item>;
result = result.Union(newSourc.Where(predicate)).ToList();
}
}
return result;
}
}
我正在使用 MVVM 使用 DirectoryInfo 及其所有子目录和文件填充 TreeView。
然后我想使用 LINQ .where() 搜索树视图,但我只搜索顶级目录而不是文件。
我正在使用递归方法创建 treeview/DirectoryInfo:
public class ItemProvider
{
public ObservableCollection<Item> GetItems(string path)
{
var items = new ObservableCollection<Item>();
if (System.IO.Directory.Exists(path))
{
var dirInfo = new DirectoryInfo(path);
foreach (var directory in dirInfo.EnumerateDirectories())
{
var item = new DirectoryItem
{
Name = directory.Name,
Path = directory.FullName,
Items = GetItems(directory.FullName)
};
items.Add(item);
}
foreach (var file in dirInfo.EnumerateFiles())
{
InteropBitmap thumbImg = ShellFile.FromFilePath(file.FullName).Thumbnail.BitmapSource as InteropBitmap;
thumbImg.Freeze();
var item = new FamilyItem
{
Name = file.Name,
Path = file.FullName,
FamImage = thumbImg
};
if (item.Name.Contains(".rfa"))
{
items.Add(item);
}
}
return items;
}
else
{
return items;
}
}
DirectoryItem 和 FamilyItem 都继承了一个名为 Item:
的模型商品型号:
public class Item
{
public string Name { get; set; }
public string Path { get; set; }
public InteropBitmap FamImage { get; set; }
}
DirectoryItem 模型:
public class DirectoryItem : Item
{
public ObservableCollection<Item> Items { get; set; }
public DirectoryItem()
{
Items = new ObservableCollection<Item>();
}
}
家庭项目:
public class FamilyItem : Item
{
}
我正在过滤集合:
Items = new ObservableCollection<Item>(ItemsCache.Where(x => x.Name.ToLower().Contains(SearchText.ToLower())));
我只得到匹配的顶级目录 - 我想得到所有匹配的“结束”文件 - 我该怎么做?
好的,修改答案。 您必须将您的 collection 正手压平(或将其压平)。
public ObservableCollection<Item> GetItemsFlat(string path)
{
var items = new ObservableCollection<Item>();
if (!System.IO.Directory.Exists(path))
return items;
var dirInfo = new DirectoryInfo(path);
foreach (var directory in dirInfo.EnumerateDirectories())
{
var item = new DirectoryItem
{
Name = directory.Name,
Path = directory.FullName,
Items = GetItems(directory.FullName)
};
items.Add(item);
foreach (var item in GetItemsFlat(directory.FullName))
items.Add(item);
}
foreach (var file in dirInfo.EnumerateFiles("*.rfa"))
{
InteropBitmap thumbImg = ShellFile.FromFilePath(file.FullName).Thumbnail.BitmapSource as InteropBitmap;
thumbImg.Freeze();
var item = new FamilyItem
{
Name = file.Name,
Path = file.FullName,
FamImage = thumbImg
};
items.Add(item)
}
}
使用 Path
(即全名)属性 进行过滤,将文件包含在匹配的子目录中,即。
ItemsCache.Where(x => x.Path.ToLower().Contains(SearchText.ToLower()))
还重构您的代码以使用“return 及早”策略。 (https://dev.to/jpswade/return-early-12o5)
即。代替
if (System.IO.Directory.Exists(path)) { ...lots of code }
做
if (!System.IO.Directory.Exists(path)) return EmptyCollection;`
...lots of code
您还可以改进此代码以丢弃 collection 中的 'empty' 目录子树。
同时检查 GetFileSystemInfo
https://docs.microsoft.com/en-us/dotnet/api/system.io.directoryinfo.getfilesysteminfos?view=net-6.0 可用于搜索包括子目录的文件
您可以通过递归版本覆盖 .Where(..)
:
public static class ExtenstioMethods
{
public static IEnumerable<Item> Where<Item>(this IEnumerable<Item> source, Func<Item, bool> predicate)
{
var result = new List<Item>();
foreach (var item in source)
{
if ((item is FamilyItem) && predicate(item))
{
result.Add(item);
}
else if (item is DirectoryItem)
{
var newSourc = ((item as DirectoryItem).Items) as IEnumerable<Item>;
result = result.Union(newSourc.Where(predicate)).ToList();
}
}
return result;
}
}