Finish MVVM conversion
This commit is contained in:
parent
9e06c343c1
commit
2a7e185dc3
@ -163,6 +163,7 @@ namespace ApplicationServices
|
||||
using var context = DbContexts.GetContext();
|
||||
|
||||
var udi = libraryBook.UserDefinedItem;
|
||||
udi.Tags = newTags;
|
||||
|
||||
// Attach() NoTracking entities before SaveChanges()
|
||||
context.Attach(udi).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
|
||||
@ -186,6 +187,7 @@ namespace ApplicationServices
|
||||
using var context = DbContexts.GetContext();
|
||||
|
||||
var udi = libraryBook.UserDefinedItem;
|
||||
udi.BookStatus = liberatedStatus;
|
||||
|
||||
// Attach() NoTracking entities before SaveChanges()
|
||||
context.Attach(udi).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
|
||||
@ -209,6 +211,7 @@ namespace ApplicationServices
|
||||
using var context = DbContexts.GetContext();
|
||||
|
||||
var udi = libraryBook.UserDefinedItem;
|
||||
udi.PdfStatus = liberatedStatus;
|
||||
|
||||
// Attach() NoTracking entities before SaveChanges()
|
||||
context.Attach(udi).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
|
||||
|
||||
@ -44,8 +44,12 @@ namespace DataLayer
|
||||
get => _tags;
|
||||
set
|
||||
{
|
||||
_tags = sanitize(value);
|
||||
ItemChanged?.Invoke(this, nameof(Tags));
|
||||
var newTags = sanitize(value);
|
||||
if (_tags != newTags)
|
||||
{
|
||||
_tags = newTags;
|
||||
ItemChanged?.Invoke(this, nameof(Tags));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -384,15 +384,14 @@ namespace LibationWinForms
|
||||
|
||||
#region liberate menu
|
||||
private async void beginBookBackupsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
=> await BookLiberation.ProcessorAutomationController.BackupAllBooksAsync(updateGridRow);
|
||||
=> await BookLiberation.ProcessorAutomationController.BackupAllBooksAsync();
|
||||
|
||||
private async void beginPdfBackupsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
=> await BookLiberation.ProcessorAutomationController.BackupAllPdfsAsync(updateGridRow);
|
||||
=> await BookLiberation.ProcessorAutomationController.BackupAllPdfsAsync();
|
||||
|
||||
private async void convertAllM4bToMp3ToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
=> await BookLiberation.ProcessorAutomationController.ConvertAllBooksAsync();
|
||||
|
||||
private void updateGridRow(object _, LibraryBook libraryBook) => currProductsGrid.RefreshLiberatedStatus(libraryBook);
|
||||
#endregion
|
||||
|
||||
#region Export menu
|
||||
|
||||
@ -12,6 +12,9 @@ using Dinah.Core.Drawing;
|
||||
|
||||
namespace LibationWinForms
|
||||
{
|
||||
/// <summary>
|
||||
/// The View Model for a LibraryBook
|
||||
/// </summary>
|
||||
internal class GridEntry : AsyncNotifyPropertyChanged, IMemberComparable
|
||||
{
|
||||
#region implementation properties
|
||||
@ -26,12 +29,15 @@ namespace LibationWinForms
|
||||
|
||||
private Book Book => LibraryBook.Book;
|
||||
private Image _cover;
|
||||
private Action _refilter;
|
||||
|
||||
public GridEntry(LibraryBook libraryBook)
|
||||
public GridEntry(LibraryBook libraryBook, Action refilterOnChanged = null)
|
||||
{
|
||||
LibraryBook = libraryBook;
|
||||
_refilter = refilterOnChanged;
|
||||
_memberValues = CreateMemberValueDictionary();
|
||||
|
||||
|
||||
//Get cover art. If it's default, subscribe to PictureCached
|
||||
{
|
||||
(bool isDefault, byte[] picture) = FileManager.PictureStorage.GetPicture(new FileManager.PictureDefinition(Book.PictureId, FileManager.PictureSize._80x80));
|
||||
@ -58,7 +64,7 @@ namespace LibationWinForms
|
||||
Description = GetDescriptionDisplay(Book);
|
||||
}
|
||||
|
||||
//DisplayTags and Liberate properties are live.
|
||||
UserDefinedItem.ItemChanged += UserDefinedItem_ItemChanged;
|
||||
}
|
||||
|
||||
private void PictureStorage_PictureCached(object sender, FileManager.PictureCachedEventArgs e)
|
||||
@ -70,7 +76,48 @@ namespace LibationWinForms
|
||||
}
|
||||
}
|
||||
|
||||
#region Data Source properties
|
||||
#region detect changes to the model and update the view
|
||||
|
||||
/// <summary>
|
||||
/// This event handler receives notifications from the model that it has changed.
|
||||
/// Save to the database and notify the view that it's changed.
|
||||
/// </summary>
|
||||
private void UserDefinedItem_ItemChanged(object sender, string itemName)
|
||||
{
|
||||
var udi = sender as UserDefinedItem;
|
||||
|
||||
if (udi.Book.AudibleProductId != LibraryBook.Book.AudibleProductId)
|
||||
return;
|
||||
|
||||
switch (itemName)
|
||||
{
|
||||
case nameof(udi.Tags):
|
||||
{
|
||||
LibraryCommands.UpdateTags(LibraryBook.Book, udi.Tags);
|
||||
NotifyPropertyChanged(nameof(DisplayTags));
|
||||
}
|
||||
break;
|
||||
case nameof(udi.BookStatus):
|
||||
{
|
||||
var status = udi.BookStatus == LiberatedStatus.PartialDownload ? LiberatedStatus.NotLiberated : udi.BookStatus;
|
||||
LibraryCommands.UpdateBook(LibraryBook.Book, status);
|
||||
NotifyPropertyChanged(nameof(Liberate));
|
||||
}
|
||||
break;
|
||||
case nameof(udi.PdfStatus):
|
||||
{
|
||||
LibraryCommands.UpdatePdf(LibraryBook.Book, udi.PdfStatus);
|
||||
NotifyPropertyChanged(nameof(Liberate));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
_refilter?.Invoke();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Model properties exposed to the view
|
||||
public Image Cover
|
||||
{
|
||||
get
|
||||
@ -95,8 +142,22 @@ namespace LibationWinForms
|
||||
public string Category { get; }
|
||||
public string Misc { get; }
|
||||
public string Description { get; }
|
||||
public string DisplayTags => string.Join("\r\n", Book.UserDefinedItem.TagsEnumerated);
|
||||
public (LiberatedStatus BookStatus, LiberatedStatus? PdfStatus) Liberate => (LibraryCommands.Liberated_Status(Book), LibraryCommands.Pdf_Status(Book));
|
||||
public string DisplayTags
|
||||
{
|
||||
get=> Book.UserDefinedItem.Tags;
|
||||
set => Book.UserDefinedItem.Tags = value;
|
||||
}
|
||||
public (LiberatedStatus BookStatus, LiberatedStatus? PdfStatus) Liberate
|
||||
{
|
||||
get => (LibraryCommands.Liberated_Status(LibraryBook.Book), LibraryCommands.Pdf_Status(LibraryBook.Book));
|
||||
|
||||
set
|
||||
{
|
||||
LibraryBook.Book.UserDefinedItem.BookStatus = value.BookStatus;
|
||||
LibraryBook.Book.UserDefinedItem.PdfStatus = value.PdfStatus;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Data Sorting
|
||||
@ -199,5 +260,12 @@ namespace LibationWinForms
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
~GridEntry()
|
||||
{
|
||||
UserDefinedItem.ItemChanged -= UserDefinedItem_ItemChanged;
|
||||
FileManager.PictureStorage.PictureCached -= PictureStorage_PictureCached;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ namespace LibationWinForms
|
||||
}
|
||||
|
||||
// else: liberate
|
||||
await BookLiberation.ProcessorAutomationController.BackupSingleBookAsync(libraryBook, (_, __) => RefreshRow(libraryBook.Book.AudibleProductId));
|
||||
await BookLiberation.ProcessorAutomationController.BackupSingleBookAsync(libraryBook);
|
||||
}
|
||||
|
||||
private void Details_Click(GridEntry liveGridEntry)
|
||||
@ -95,15 +95,10 @@ namespace LibationWinForms
|
||||
if (bookDetailsForm.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
|
||||
var qtyChanges = LibraryCommands.UpdateUserDefinedItem(liveGridEntry.LibraryBook.Book, bookDetailsForm.NewTags, bookDetailsForm.BookLiberatedStatus, bookDetailsForm.PdfLiberatedStatus);
|
||||
if (qtyChanges == 0)
|
||||
return;
|
||||
liveGridEntry.DisplayTags = bookDetailsForm.NewTags;
|
||||
liveGridEntry.Liberate = (bookDetailsForm.BookLiberatedStatus, bookDetailsForm.PdfLiberatedStatus);
|
||||
|
||||
//Re-apply filters
|
||||
Filter();
|
||||
|
||||
//Update whole GridEntry row
|
||||
liveGridEntry.NotifyPropertyChanged();
|
||||
BackupCountsChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -132,7 +127,7 @@ namespace LibationWinForms
|
||||
}
|
||||
|
||||
var orderedGridEntries = lib
|
||||
.Select(lb => new GridEntry(lb)).ToList()
|
||||
.Select(lb => new GridEntry(lb, Filter)).ToList()
|
||||
// default load order
|
||||
.OrderByDescending(ge => (DateTime)ge.GetMemberValue(nameof(ge.PurchaseDate)))
|
||||
//// more advanced example: sort by author, then series, then title
|
||||
@ -150,19 +145,6 @@ namespace LibationWinForms
|
||||
BackupCountsChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void RefreshRow(string productId)
|
||||
{
|
||||
var liveGridEntry = getGridEntry((ge) => ge.AudibleProductId == productId);
|
||||
|
||||
// update GridEntry Liberate cell
|
||||
liveGridEntry?.NotifyPropertyChanged(nameof(liveGridEntry.Liberate));
|
||||
|
||||
// needed in case filtering by -IsLiberated and it gets changed to Liberated. want to immediately show the change
|
||||
Filter();
|
||||
|
||||
BackupCountsChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Filter
|
||||
@ -195,12 +177,7 @@ namespace LibationWinForms
|
||||
#endregion
|
||||
|
||||
#region DataGridView Macro
|
||||
|
||||
private GridEntry getGridEntry(Func<GridEntry, bool> predicate)
|
||||
=> ((SortableBindingList<GridEntry>)gridEntryBindingSource.DataSource).FirstOrDefault(predicate);
|
||||
|
||||
private GridEntry getGridEntry(int rowIndex) => _dataGridView.GetBoundItem<GridEntry>(rowIndex);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user