diff --git a/ApplicationServices/LibraryCommands.cs b/ApplicationServices/LibraryCommands.cs index f58fc3d0..a108b530 100644 --- a/ApplicationServices/LibraryCommands.cs +++ b/ApplicationServices/LibraryCommands.cs @@ -176,6 +176,7 @@ namespace ApplicationServices int qtyChanges = saveChanges(context); logTime("importIntoDbAsync -- post SaveChanges"); + // this is any changes at all to the database, not just new books if (qtyChanges > 0) await Task.Run(() => finalizeLibrarySizeChange()); logTime("importIntoDbAsync -- post finalizeLibrarySizeChange"); diff --git a/LibationWinForms/Form1.cs b/LibationWinForms/Form1.cs index 97edf43e..597bab13 100644 --- a/LibationWinForms/Form1.cs +++ b/LibationWinForms/Form1.cs @@ -75,16 +75,22 @@ namespace LibationWinForms { SuspendLayout(); { - if (productsGrid != null) + // previous non-null grid with zero-count removes columns. remove/re-add grid to get columns back + if (productsGrid?.Count == 0) { gridPanel.Controls.Remove(productsGrid); productsGrid.VisibleCountChanged -= setVisibleCount; productsGrid.Dispose(); + productsGrid = null; + } + + if (productsGrid is null) + { + productsGrid = new ProductsGrid { Dock = DockStyle.Fill }; + productsGrid.VisibleCountChanged += setVisibleCount; + gridPanel.UIThreadSync(() => gridPanel.Controls.Add(productsGrid)); } - productsGrid = new ProductsGrid { Dock = DockStyle.Fill }; - productsGrid.VisibleCountChanged += setVisibleCount; - gridPanel.UIThreadSync(() => gridPanel.Controls.Add(productsGrid)); productsGrid.Display(); } ResumeLayout(); diff --git a/LibationWinForms/grid/ProductsGrid.cs b/LibationWinForms/grid/ProductsGrid.cs index ba83ca2d..7f933bad 100644 --- a/LibationWinForms/grid/ProductsGrid.cs +++ b/LibationWinForms/grid/ProductsGrid.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; @@ -107,25 +108,18 @@ namespace LibationWinForms #endregion - private SortableBindingList bindingList; - - /// Insert ad hoc library books to top of grid - public void AddToTop(DataLayer.LibraryBook libraryBook) => bindingList.Insert(0, toGridEntry(libraryBook)); - #region UI display functions - private bool hasBeenDisplayed = false; + public int Count { get; private set; } + + private SortableBindingList bindingList; + public void Display() { - if (hasBeenDisplayed) - return; - hasBeenDisplayed = true; - - // - // transform into sorted GridEntry.s BEFORE binding - // var lib = DbContexts.GetLibrary_Flat_NoTracking(); + Count = lib.Count; + // if no data. hide all columns. return if (!lib.Any()) { @@ -134,25 +128,59 @@ namespace LibationWinForms return; } - var orderedGridEntries = lib - .Select(lb => toGridEntry(lb)) + var orderedBooks = lib // default load order - .OrderByDescending(ge => (DateTime)ge.GetMemberValue(nameof(ge.PurchaseDate))) + .OrderByDescending(lb => lb.DateAdded) //// more advanced example: sort by author, then series, then title - //.OrderBy(ge => ge.Authors) - // .ThenBy(ge => ge.Series) - // .ThenBy(ge => ge.Title) + //.OrderBy(lb => lb.Book.AuthorNames) + // .ThenBy(lb => lb.Book.SeriesSortable) + // .ThenBy(lb => lb.Book.TitleSortable) .ToList(); // BIND - bindingList = new SortableBindingList(orderedGridEntries); - gridEntryBindingSource.DataSource = bindingList; + if (bindingList is null) + bindToGrid(orderedBooks); + else + updateGrid(orderedBooks); // FILTER Filter(); } - private GridEntry toGridEntry(DataLayer.LibraryBook libraryBook) + private void bindToGrid(List orderedBooks) + { + bindingList = new SortableBindingList(orderedBooks.Select(lb => toGridEntry(lb))); + gridEntryBindingSource.DataSource = bindingList; + } + + private void updateGrid(List orderedBooks) + { + for (var i = orderedBooks.Count - 1; i >= 0; i--) + { + var libraryBook = orderedBooks[i]; + var existingItem = bindingList.FirstOrDefault(i => i.AudibleProductId == libraryBook.Book.AudibleProductId); + + // add new to top + if (existingItem is null) + bindingList.Insert(0, toGridEntry(libraryBook)); + // update existing + else + existingItem.UpdateLibraryBook(libraryBook); + } + + // remove deleted from grid. note: actual deletion from db must still occur via the RemoveBook feature. deleting from audible will not trigger this + var oldIds = bindingList.Select(ge => ge.AudibleProductId).ToList(); + var newIds = orderedBooks.Select(lb => lb.Book.AudibleProductId).ToList(); + var remove = oldIds.Except(newIds).ToList(); + foreach (var id in remove) + { + var oldItem = bindingList.FirstOrDefault(ge => ge.AudibleProductId == id); + if (oldItem is not null) + bindingList.Remove(oldItem); + } + } + + private GridEntry toGridEntry(DataLayer.LibraryBook libraryBook) { var entry = new GridEntry(libraryBook); entry.Committed += Filter;