diff --git a/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs b/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs
index 127a3b00..8f6f1485 100644
--- a/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs
+++ b/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs
@@ -23,7 +23,7 @@ namespace LibationAvalonia.ViewModels
/// Backing list of all grid entries
private readonly AvaloniaList SOURCE = new();
/// Grid entries included in the filter set. If null, all grid entries are shown
- private List FilteredInGridEntries;
+ private HashSet FilteredInGridEntries;
public string FilterString { get; private set; }
public DataGridCollectionView GridEntries { get; private set; }
@@ -117,8 +117,8 @@ namespace LibationAvalonia.ViewModels
}
//Create the filtered-in list before adding entries to avoid a refresh
- FilteredInGridEntries = QueryResults(geList.Union(geList.OfType().SelectMany(s => s.Children)), FilterString);
- SOURCE.AddRange(geList.OrderByDescending(e => e.DateAdded));
+ FilteredInGridEntries = geList.Union(geList.OfType().SelectMany(s => s.Children)).FilterEntries(FilterString);
+ SOURCE.AddRange(geList.OrderDescending(new RowComparer(null)));
//Add all children beneath their parent
foreach (var series in SOURCE.OfType().ToList())
@@ -301,7 +301,7 @@ namespace LibationAvalonia.ViewModels
if (SOURCE.Count == 0)
return;
- FilteredInGridEntries = QueryResults(SOURCE, searchString);
+ FilteredInGridEntries = SOURCE.FilterEntries(searchString);
await refreshGrid();
}
@@ -318,25 +318,11 @@ namespace LibationAvalonia.ViewModels
return FilteredInGridEntries.Contains(item);
}
- private static List QueryResults(IEnumerable entries, string searchString)
- {
- if (string.IsNullOrEmpty(searchString)) return null;
-
- var searchResultSet = SearchEngineCommands.Search(searchString);
-
- var booksFilteredIn = entries.BookEntries().Join(searchResultSet.Docs, lbe => lbe.AudibleProductId, d => d.ProductId, (lbe, d) => (IGridEntry)lbe);
-
- //Find all series containing children that match the search criteria
- var seriesFilteredIn = entries.SeriesEntries().Where(s => s.Children.Join(searchResultSet.Docs, lbe => lbe.AudibleProductId, d => d.ProductId, (lbe, d) => lbe).Any());
-
- return booksFilteredIn.Concat(seriesFilteredIn).ToList();
- }
-
private async void SearchEngineCommands_SearchEngineUpdated(object sender, EventArgs e)
{
- var filterResults = QueryResults(SOURCE, FilterString);
+ var filterResults = SOURCE.FilterEntries(FilterString);
- if (filterResults is not null && FilteredInGridEntries.Intersect(filterResults).Count() != FilteredInGridEntries.Count)
+ if (FilteredInGridEntries.SearchSetsDiffer(filterResults))
{
FilteredInGridEntries = filterResults;
await refreshGrid();
diff --git a/Source/LibationAvalonia/ViewModels/RowComparer.cs b/Source/LibationAvalonia/ViewModels/RowComparer.cs
index 743a610f..a9d40378 100644
--- a/Source/LibationAvalonia/ViewModels/RowComparer.cs
+++ b/Source/LibationAvalonia/ViewModels/RowComparer.cs
@@ -1,98 +1,28 @@
using Avalonia.Controls;
using LibationUiBase.GridView;
-using System.Collections;
-using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
namespace LibationAvalonia.ViewModels
{
- ///
- /// This compare class ensures that all top-level grid entries (standalone books or series parents)
- /// are sorted by PropertyName while all episodes remain immediately beneath their parents and remain
- /// sorted by series index, ascending. Stable sorting is achieved by comparing the GridEntry.ListIndex
- /// properties when 2 items compare equal.
- ///
- internal class RowComparer : IComparer, IComparer, IComparer