Search code examples
c#mvvmtreeviewdirectoryinfo

Filter an ObservableCollection of DirectoryInfo with LINQ


I'm using MVVM to populate a TreeView with a DirectoryInfo and all its sub-directories and files.

I then want to search through the treeview with LINQ .where() but I'm only searching the top directories and not the files.

I'm creating the treeview/DirectoryInfo with a recursive method:

  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 and FamilyItem both inherits a model called Item:

Item model:

public class Item
    {
        public string Name { get; set; }
        public string Path { get; set; }
        public InteropBitmap FamImage { get; set; }
    }

DirectoryItem model:

public class DirectoryItem : Item

    {
        public ObservableCollection<Item> Items { get; set; }
    
        public DirectoryItem()
        {
        Items = new ObservableCollection<Item>();
        }
    }

FamilyItem:

 public class FamilyItem : Item
    {

    }

I'm filtering the collection with:

Items = new ObservableCollection<Item>(ItemsCache.Where(x => x.Name.ToLower().Contains(SearchText.ToLower())));

I only get the top directories that match - I want to get all the "end" files that match - how would I go about doing that?


Solution

  • You can override .Where(..) by a recursive version:

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