Move filtering into SyncBindingSource

This commit is contained in:
Michael Bucari-Tovo 2022-05-15 19:58:59 -06:00
parent 3a5ef999f0
commit 255c0a3359
2 changed files with 43 additions and 43 deletions

View File

@ -1,5 +1,8 @@
using System; using ApplicationServices;
using Dinah.Core.DataBinding;
using System;
using System.ComponentModel; using System.ComponentModel;
using System.Linq;
using System.Threading; using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
@ -17,6 +20,33 @@ namespace LibationWinForms
public SyncBindingSource(object dataSource, string dataMember) : base(dataSource, dataMember) public SyncBindingSource(object dataSource, string dataMember) : base(dataSource, dataMember)
=> syncContext = SynchronizationContext.Current; => syncContext = SynchronizationContext.Current;
public override bool SupportsFiltering => true;
public override string Filter { get => filterString; set => SetFilter(value); }
private string filterString;
private void SetFilter(string searchString)
{
if (searchString != filterString)
RemoveFilter();
filterString = searchString;
var searchResults = SearchEngineCommands.Search(searchString);
var productIds = searchResults.Docs.Select(d => d.ProductId).ToList();
var allItems = ((SortableBindingList<GridEntry>)DataSource).InnerList;
var filterList = productIds.Join(allItems, s => s, ge => ge.AudibleProductId, (pid, ge) => ge).ToList();
((SortableBindingList<GridEntry>)DataSource).SetFilteredItems(filterList);
}
public override void RemoveFilter()
{
((SortableBindingList<GridEntry>)DataSource).RemoveFilter();
base.RemoveFilter();
}
protected override void OnListChanged(ListChangedEventArgs e) protected override void OnListChanged(ListChangedEventArgs e)
{ {
if (syncContext is not null) if (syncContext is not null)

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -55,8 +56,6 @@ namespace LibationWinForms
EnableDoubleBuffering(); EnableDoubleBuffering();
// sorting breaks filters. must reapply filters after sorting
_dataGridView.Sorted += reapplyFilter;
_dataGridView.CellContentClick += DataGridView_CellContentClick; _dataGridView.CellContentClick += DataGridView_CellContentClick;
this.Load += ProductsGrid_Load; this.Load += ProductsGrid_Load;
@ -184,14 +183,13 @@ namespace LibationWinForms
else else
bindToGrid(orderedBooks); bindToGrid(orderedBooks);
// re-apply previous filter
reapplyFilter();
if (!hasBeenDisplayed) if (!hasBeenDisplayed)
{ {
hasBeenDisplayed = true; hasBeenDisplayed = true;
InitialLoaded?.Invoke(this, new()); InitialLoaded?.Invoke(this, new());
} }
} }
private void bindToGrid(List<DataLayer.LibraryBook> orderedBooks) private void bindToGrid(List<DataLayer.LibraryBook> orderedBooks)
@ -230,7 +228,6 @@ namespace LibationWinForms
private GridEntry toGridEntry(DataLayer.LibraryBook libraryBook) private GridEntry toGridEntry(DataLayer.LibraryBook libraryBook)
{ {
var entry = new GridEntry(libraryBook); var entry = new GridEntry(libraryBook);
entry.Committed += reapplyFilter;
// see also notes in Libation/Source/__ARCHITECTURE NOTES.txt :: MVVM // see also notes in Libation/Source/__ARCHITECTURE NOTES.txt :: MVVM
entry.LibraryBookUpdated += (sender, _) => _dataGridView.InvalidateRow(_dataGridView.GetRowIdOfBoundItem((GridEntry)sender)); entry.LibraryBookUpdated += (sender, _) => _dataGridView.InvalidateRow(_dataGridView.GetRowIdOfBoundItem((GridEntry)sender));
return entry; return entry;
@ -240,53 +237,26 @@ namespace LibationWinForms
#region Filter #region Filter
private string _filterSearchString;
private void reapplyFilter(object _ = null, EventArgs __ = null) => Filter(_filterSearchString);
public void Filter(string searchString) public void Filter(string searchString)
{ {
// empty string is valid. null is not
if (searchString is null)
return;
_filterSearchString = searchString;
if (_dataGridView.Rows.Count == 0) if (_dataGridView.Rows.Count == 0)
return; return;
var initVisible = getVisible().Count(); if (string.IsNullOrEmpty(searchString))
gridEntryBindingSource.RemoveFilter();
else
gridEntryBindingSource.Filter = searchString;
var searchResults = SearchEngineCommands.Search(searchString);
var productIds = searchResults.Docs.Select(d => d.ProductId).ToList();
// https://stackoverflow.com/a/18942430 VisibleCountChanged?.Invoke(this, bindingList.Count);
var bindingContext = BindingContext[_dataGridView.DataSource];
bindingContext.SuspendBinding();
{
this.UIThreadSync(() =>
{
for (var r = _dataGridView.RowCount - 1; r >= 0; r--)
_dataGridView.Rows[r].Visible = productIds.Contains(getGridEntry(r).AudibleProductId);
});
}
// Causes repainting of the DataGridView
bindingContext.ResumeBinding();
var endVisible = getVisible().Count();
if (initVisible != endVisible)
VisibleCountChanged?.Invoke(this, endVisible);
} }
#endregion #endregion
private IEnumerable<DataGridViewRow> getVisible() internal List<LibraryBook> GetVisible()
=> _dataGridView => bindingList
.AsEnumerable() .InnerList
.Where(row => row.Visible); .Select(row => row.LibraryBook)
internal List<DataLayer.LibraryBook> GetVisible()
=> getVisible()
.Select(row => ((GridEntry)row.DataBoundItem).LibraryBook)
.ToList(); .ToList();
private GridEntry getGridEntry(int rowIndex) => _dataGridView.GetBoundItem<GridEntry>(rowIndex); private GridEntry getGridEntry(int rowIndex) => _dataGridView.GetBoundItem<GridEntry>(rowIndex);