使用 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;
      }
   }