Use ReactiveUI.

Sort of fix remove book checkbox column.
This commit is contained in:
Michael Bucari-Tovo 2022-07-12 18:55:10 -06:00
parent 5f45d28b9f
commit 6e091230cf
11 changed files with 171 additions and 159 deletions

View File

@ -1,35 +1,15 @@
using Avalonia.Controls;
using Avalonia.Controls.Utils;
using Avalonia.Interactivity;
using LibationWinForms.AvaloniaUI.ViewModels;
using System;
using System.Linq;
namespace LibationWinForms.AvaloniaUI.Controls
{
/// <summary> The purpose of this extension is to immediately commit any check state changes to the viewmodel </summary>
/// <summary> The purpose of this extension WAS to immediately commit any check state changes to the viewmodel, but for the life of me I cannot get it to work! </summary>
public partial class DataGridCheckBoxColumnExt : DataGridCheckBoxColumn
{
protected override IControl GenerateEditingElementDirect(DataGridCell cell, object dataItem)
{
var ele = base.GenerateEditingElementDirect(cell, dataItem) as CheckBox;
ele.Checked += EditingElement_Checked;
ele.Unchecked += EditingElement_Checked;
ele.Indeterminate += EditingElement_Checked;
return ele;
}
private void EditingElement_Checked(object sender, RoutedEventArgs e)
{
if (sender is CheckBox cbox && cbox.DataContext is GridEntry2 gentry)
{
gentry.Remove = cbox.IsChecked;
FindDataGridParent(cbox)?.CommitEdit(DataGridEditingUnit.Cell, false);
}
}
DataGrid? FindDataGridParent(IControl? control)
{
if (control?.Parent is null) return null;
else if (control?.Parent is DataGrid dg) return dg;
else return FindDataGridParent(control?.Parent);
}
}
}

View File

@ -2,8 +2,8 @@
{
public class BookTags
{
public string Tags { get; init; }
public bool IsSeries { get; init; }
public bool HasTags => !string.IsNullOrEmpty(Tags);
private string _tags;
public string Tags { get => _tags; init { _tags = value; HasTags = !string.IsNullOrEmpty(_tags); } }
public bool HasTags { get; init; }
}
}

View File

@ -21,7 +21,7 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
SomeRemoved
}
/// <summary>The View Model base for the DataGridView</summary>
public abstract class GridEntry2 : AsyncNotifyPropertyChanged2, IMemberComparable
public abstract class GridEntry2 : ViewModelBase
{
[Browsable(false)] public string AudibleProductId => Book.AudibleProductId;
[Browsable(false)] public LibraryBook LibraryBook { get; protected set; }
@ -32,30 +32,35 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
#region Model properties exposed to the view
private Avalonia.Media.Imaging.Bitmap _cover;
private string _purchaseDate;
private string _series;
private string _title;
private string _length;
private string _authors;
private string _narrators;
private string _category;
private string _misc;
private string _description;
private string _productRating;
private string _myRating;
public Avalonia.Media.Imaging.Bitmap Cover { get => _cover; protected set { this.RaiseAndSetIfChanged(ref _cover, value); } }
public string PurchaseDate { get => _purchaseDate; protected set { this.RaiseAndSetIfChanged(ref _purchaseDate, value); } }
public string Series { get => _series; protected set { this.RaiseAndSetIfChanged(ref _series, value); } }
public string Title { get => _title; protected set { this.RaiseAndSetIfChanged(ref _title, value); } }
public string Length { get => _length; protected set { this.RaiseAndSetIfChanged(ref _length, value); } }
public string Authors { get => _authors; protected set { this.RaiseAndSetIfChanged(ref _authors, value); } }
public string Narrators { get => _narrators; protected set { this.RaiseAndSetIfChanged(ref _narrators, value); } }
public string Category { get => _category; protected set { this.RaiseAndSetIfChanged(ref _category, value); } }
public string Misc { get => _misc; protected set { this.RaiseAndSetIfChanged(ref _misc, value); } }
public string Description { get => _description; protected set { this.RaiseAndSetIfChanged(ref _description, value); } }
public string ProductRating { get => _productRating; protected set { this.RaiseAndSetIfChanged(ref _productRating, value); } }
public string MyRating { get => _myRating; protected set { this.RaiseAndSetIfChanged(ref _myRating, value); } }
protected bool? _remove = false;
public abstract bool? Remove { get; set; }
public abstract LiberateButtonStatus2 Liberate { get; }
public Avalonia.Media.Imaging.Bitmap Cover
{
get => _cover;
protected set
{
_cover = value;
NotifyPropertyChanged();
}
}
public string PurchaseDate { get; protected set; }
public string Series { get; protected set; }
public string Title { get; protected set; }
public string Length { get; protected set; }
public string Authors { get; set; }
public string Narrators { get; protected set; }
public string Category { get; protected set; }
public string Misc { get; protected set; }
public string Description { get; protected set; }
public string ProductRating { get; protected set; }
public string MyRating { get; protected set; }
public abstract BookTags BookTags { get; }
#endregion
@ -87,7 +92,6 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
#region Cover Art
private Avalonia.Media.Imaging.Bitmap _cover;
protected void LoadCover()
{
// Get cover art. If it's default, subscribe to PictureCached

View File

@ -1,13 +1,12 @@
using Avalonia.Media.Imaging;
using DataLayer;
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace LibationWinForms.AvaloniaUI.ViewModels
{
public class LiberateButtonStatus2 : IComparable, INotifyPropertyChanged
public class LiberateButtonStatus2 : ViewModelBase, IComparable
{
public LiberatedStatus BookStatus { get; set; }
public LiberatedStatus? PdfStatus { get; set; }
@ -18,10 +17,9 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
get => _expanded;
set
{
_expanded = value;
NotifyPropertyChanged();
NotifyPropertyChanged(nameof(Image));
NotifyPropertyChanged(nameof(ToolTip));
this.RaiseAndSetIfChanged(ref _expanded, value);
this.RaisePropertyChanged(nameof(Image));
this.RaisePropertyChanged(nameof(ToolTip));
}
}
public bool IsSeries { get; init; }
@ -30,13 +28,7 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
static Dictionary<string, Bitmap> images = new();
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
/// <summary>
/// Defines the Liberate column's sorting behavior
/// </summary>
/// <summary> Defines the Liberate column's sorting behavior </summary>
public int CompareTo(object obj)
{
if (obj is not LiberateButtonStatus2 second) return -1;
@ -49,14 +41,13 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
else return BookStatus.CompareTo(second.BookStatus);
}
private Bitmap GetLiberateIcon()
{
if (IsSeries)
return Expanded ? GetFromresc("minus") : GetFromresc("plus");
return Expanded ? GetFromResources("minus") : GetFromResources("plus");
if (BookStatus == LiberatedStatus.Error)
return GetFromresc("error");
return GetFromResources("error");
string image_lib = BookStatus switch
{
@ -75,7 +66,7 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
_ => throw new Exception("Unexpected PDF state")
};
return GetFromresc($"liberate_{image_lib}{image_pdf}");
return GetFromResources($"liberate_{image_lib}{image_pdf}");
}
private string GetTooltip()
{
@ -113,7 +104,7 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
return mouseoverText;
}
private static Bitmap GetFromresc(string rescName)
private static Bitmap GetFromResources(string rescName)
{
if (images.ContainsKey(rescName)) return images[rescName];

View File

@ -2,6 +2,7 @@
using DataLayer;
using Dinah.Core;
using LibationWinForms.GridView;
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@ -27,8 +28,9 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
set
{
_remove = value.HasValue ? value.Value : false;
Parent?.ChildRemoveUpdate();
NotifyPropertyChanged();
this.RaisePropertyChanged(nameof(Remove));
}
}
@ -84,20 +86,6 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
Description = TrimTextToWord(LongDescription, 62);
SeriesIndex = Book.SeriesLink.FirstOrDefault()?.Index ?? 0;
NotifyPropertyChanged(nameof(Title));
NotifyPropertyChanged(nameof(Series));
NotifyPropertyChanged(nameof(Length));
NotifyPropertyChanged(nameof(MyRating));
NotifyPropertyChanged(nameof(PurchaseDate));
NotifyPropertyChanged(nameof(ProductRating));
NotifyPropertyChanged(nameof(Authors));
NotifyPropertyChanged(nameof(Narrators));
NotifyPropertyChanged(nameof(Category));
NotifyPropertyChanged(nameof(Misc));
NotifyPropertyChanged(nameof(LongDescription));
NotifyPropertyChanged(nameof(Description));
NotifyPropertyChanged(nameof(SeriesIndex));
UserDefinedItem.ItemChanged += UserDefinedItem_ItemChanged;
}
@ -120,18 +108,18 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
switch (itemName)
{
case nameof(udi.Tags):
Book.UserDefinedItem.Tags = udi.Tags;
NotifyPropertyChanged(nameof(BookTags));
Book.UserDefinedItem.Tags = udi.Tags;
this.RaisePropertyChanged(nameof(BookTags));
break;
case nameof(udi.BookStatus):
Book.UserDefinedItem.BookStatus = udi.BookStatus;
_bookStatus = udi.BookStatus;
NotifyPropertyChanged(nameof(Liberate));
this.RaisePropertyChanged(nameof(Liberate));
break;
case nameof(udi.PdfStatus):
Book.UserDefinedItem.PdfStatus = udi.PdfStatus;
_pdfStatus = udi.PdfStatus;
NotifyPropertyChanged(nameof(Liberate));
this.RaisePropertyChanged(nameof(Liberate));
break;
}
}

View File

@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using ApplicationServices;
using Avalonia.Media.Imaging;
@ -10,6 +8,7 @@ using DataLayer;
using Dinah.Core;
using FileLiberator;
using LibationFileManager;
using ReactiveUI;
namespace LibationWinForms.AvaloniaUI.ViewModels
{
@ -36,10 +35,9 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
/// <summary>
/// This is the viewmodel for queued processables
/// </summary>
public class ProcessBook2 : INotifyPropertyChanged
public class ProcessBook2 : ViewModelBase
{
public event EventHandler Completed;
public event PropertyChangedEventHandler PropertyChanged;
public LibraryBook LibraryBook { get; private set; }
@ -53,14 +51,14 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
private Bitmap _cover;
#region Properties exposed to the view
public ProcessBookResult Result { get => _result; set { _result = value; NotifyPropertyChanged(); NotifyPropertyChanged(nameof(StatusText)); } }
public ProcessBookStatus Status { get => _status; set { _status = value; NotifyPropertyChanged(); NotifyPropertyChanged(nameof(BackgroundColor)); NotifyPropertyChanged(nameof(IsFinished)); NotifyPropertyChanged(nameof(IsDownloading)); NotifyPropertyChanged(nameof(Queued)); } }
public string Narrator { get => _narrator; set { _narrator = value; NotifyPropertyChanged(); } }
public string Author { get => _author; set { _author = value; NotifyPropertyChanged(); } }
public string Title { get => _title; set { _title = value; NotifyPropertyChanged(); } }
public int Progress { get => _progress; private set { _progress = value; NotifyPropertyChanged(); } }
public string ETA { get => _eta; private set { _eta = value; NotifyPropertyChanged(); } }
public Bitmap Cover { get => _cover; private set { _cover = value; NotifyPropertyChanged(); } }
public ProcessBookResult Result { get => _result; set { this.RaiseAndSetIfChanged(ref _result, value); this.RaisePropertyChanged(nameof(StatusText)); } }
public ProcessBookStatus Status { get => _status; set { this.RaiseAndSetIfChanged(ref _status, value); this.RaisePropertyChanged(nameof(BackgroundColor)); this.RaisePropertyChanged(nameof(IsFinished)); this.RaisePropertyChanged(nameof(IsDownloading)); this.RaisePropertyChanged(nameof(Queued)); } }
public string Narrator { get => _narrator; set { this.RaiseAndSetIfChanged(ref _narrator, value); } }
public string Author { get => _author; set { this.RaiseAndSetIfChanged(ref _author, value); } }
public string Title { get => _title; set { this.RaiseAndSetIfChanged(ref _title, value); } }
public int Progress { get => _progress; private set { this.RaiseAndSetIfChanged(ref _progress, value); } }
public string ETA { get => _eta; private set { this.RaiseAndSetIfChanged(ref _eta, value); } }
public Bitmap Cover { get => _cover; private set { this.RaiseAndSetIfChanged(ref _cover, value); } }
public bool IsFinished => Status is not ProcessBookStatus.Queued and not ProcessBookStatus.Working;
public bool IsDownloading => Status is ProcessBookStatus.Working;
public bool Queued => Status is ProcessBookStatus.Queued;
@ -91,8 +89,6 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
private Processable _currentProcessable;
private readonly Queue<Func<Processable>> Processes = new();
private readonly ProcessQueue.LogMe Logger;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
public ProcessBook2(LibraryBook libraryBook, ProcessQueue.LogMe logme)
{

View File

@ -7,31 +7,25 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
{
public class ProcessQueueViewModel : ViewModelBase, ProcessQueue.ILogForm
{
public string QueueHeader => "this is a header!";
public ObservableCollection<LogEntry> LogEntries { get; } = new();
private TrackedQueue2<ProcessBook2> _items = new();
public ProcessQueueViewModel() { }
public TrackedQueue2<ProcessBook2> Items
{
get => _items;
set => this.RaiseAndSetIfChanged(ref _items, value);
}
public ObservableCollection<LogEntry> LogEntries { get; } = new();
public ProcessBook2 SelectedItem { get; set; }
public void WriteLine(string text)
{
Dispatcher.UIThread.Post(() =>
LogEntries.Add(new()
{
LogDate = DateTime.Now,
LogMessage = text.Trim()
}));
LogEntries.Add(new()
{
LogDate = DateTime.Now,
LogMessage = text.Trim()
}));
}
}
public class LogEntry
@ -40,5 +34,4 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
public string LogDateString => LogDate.ToShortTimeString();
public string LogMessage { get; init; }
}
}

View File

@ -1,6 +1,6 @@
using DataLayer;
using Dinah.Core;
using LibationWinForms.GridView;
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@ -21,13 +21,8 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
var removeCount = Children.Count(c => c.Remove == true);
if (removeCount == 0)
_remove = false;
else if (removeCount == Children.Count)
_remove = true;
else
_remove = null;
NotifyPropertyChanged(nameof(Remove));
_remove = removeCount == 0 ? false : (removeCount == Children.Count ? true : null);
this.RaisePropertyChanged(nameof(Remove));
}
#region Model properties exposed to the view
@ -36,7 +31,7 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
get => _remove;
set
{
_remove = value.HasValue ? value : false;
_remove = value.HasValue ? value.Value : false;
suspendCounting = true;
@ -44,13 +39,12 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
item.Remove = value;
suspendCounting = false;
NotifyPropertyChanged();
this.RaisePropertyChanged(nameof(Remove));
}
}
public override LiberateButtonStatus2 Liberate { get; }
public override BookTags BookTags { get; } = new() { IsSeries = true };
public override BookTags BookTags { get; } = new();
#endregion
@ -95,19 +89,6 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
int bookLenMins = Children.Sum(c => c.LibraryBook.Book.LengthInMinutes);
Length = bookLenMins == 0 ? "" : $"{bookLenMins / 60} hr {bookLenMins % 60} min";
NotifyPropertyChanged(nameof(Title));
NotifyPropertyChanged(nameof(Series));
NotifyPropertyChanged(nameof(Length));
NotifyPropertyChanged(nameof(MyRating));
NotifyPropertyChanged(nameof(PurchaseDate));
NotifyPropertyChanged(nameof(ProductRating));
NotifyPropertyChanged(nameof(Authors));
NotifyPropertyChanged(nameof(Narrators));
NotifyPropertyChanged(nameof(Category));
NotifyPropertyChanged(nameof(Misc));
NotifyPropertyChanged(nameof(LongDescription));
NotifyPropertyChanged(nameof(Description));
}
#region Data Sorting

View File

@ -1,3 +1,4 @@
using Avalonia.Controls;
using ReactiveUI;
using System;
using System.Collections.Generic;
@ -7,5 +8,6 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
{
public class ViewModelBase : ReactiveObject
{
}
}

View File

@ -11,7 +11,7 @@
<DataGrid Name="productsGrid" AutoGenerateColumns="False" Items="{Binding GridEntries}">
<DataGrid.Columns>
<controls:DataGridCheckBoxColumnExt IsVisible="False" Header="Remove" IsThreeState="True" IsReadOnly="False" CanUserSort="True" Binding="{Binding Remove, Mode=TwoWay}" Width="70" SortMemberPath="Remove"/>
<controls:DataGridCheckBoxColumnExt IsVisible="True" Header="Remove" IsThreeState="True" IsReadOnly="False" CanUserSort="True" Binding="{Binding Remove, Mode=TwoWay}" Width="70" SortMemberPath="Remove"/>
<DataGridTemplateColumn CanUserSort="True" Width="75" Header="Liberate" SortMemberPath="Liberate">
<DataGridTemplateColumn.CellTemplate>
@ -147,7 +147,7 @@
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button IsVisible="{Binding !BookTags.IsSeries}" Width="100" Height="80" Click="OnTagsButtonClick" ToolTip.Tip="Click to edit tags" >
<Button IsVisible="{Binding !Liberate.IsSeries}" Width="100" Height="80" Click="OnTagsButtonClick" ToolTip.Tip="Click to edit tags" >
<Panel>
<Image IsVisible="{Binding !BookTags.HasTags}" Stretch="None" Source="/AvaloniaUI/Assets/edit_25x25.png" />
<TextBlock IsVisible="{Binding BookTags.HasTags}" FontSize="12" TextWrapping="WrapWithOverflow" Text="{Binding BookTags.Tags}"/>

View File

@ -9,6 +9,7 @@ using Dinah.Core.DataBinding;
using FileLiberator;
using LibationFileManager;
using LibationWinForms.AvaloniaUI.ViewModels;
using ReactiveUI;
using System;
using System.Collections;
using System.Collections.Generic;
@ -38,6 +39,20 @@ namespace LibationWinForms.AvaloniaUI.Views
.ToList();
DataGridColumn removeGVColumn;
DataGridColumn liberateGVColumn;
DataGridColumn coverGVColumn;
DataGridColumn titleGVColumn;
DataGridColumn authorsGVColumn;
DataGridColumn narratorsGVColumn;
DataGridColumn lengthGVColumn;
DataGridColumn seriesGVColumn;
DataGridColumn descriptionGVColumn;
DataGridColumn categoryGVColumn;
DataGridColumn productRatingGVColumn;
DataGridColumn purchaseDateGVColumn;
DataGridColumn myRatingGVColumn;
DataGridColumn miscGVColumn;
DataGridColumn tagAndDetailsGVColumn;
public ProductsDisplay2()
{
InitializeComponent();
@ -45,16 +60,79 @@ namespace LibationWinForms.AvaloniaUI.Views
productsGrid = this.FindControl<DataGrid>(nameof(productsGrid));
productsGrid.Sorting += Dg1_Sorting;
productsGrid.CanUserSortColumns = true;
productsGrid.LoadingRow += ProductsGrid_LoadingRow;
removeGVColumn = productsGrid.Columns[0];
liberateGVColumn = productsGrid.Columns[1];
coverGVColumn = productsGrid.Columns[2];
titleGVColumn = productsGrid.Columns[3];
authorsGVColumn = productsGrid.Columns[4];
narratorsGVColumn = productsGrid.Columns[5];
lengthGVColumn = productsGrid.Columns[6];
seriesGVColumn = productsGrid.Columns[7];
descriptionGVColumn = productsGrid.Columns[8];
categoryGVColumn = productsGrid.Columns[9];
productRatingGVColumn = productsGrid.Columns[10];
purchaseDateGVColumn = productsGrid.Columns[11];
myRatingGVColumn = productsGrid.Columns[12];
miscGVColumn = productsGrid.Columns[13];
tagAndDetailsGVColumn = productsGrid.Columns[14];
removeGVColumn.CustomSortComparer = new RowComparer(removeGVColumn);
liberateGVColumn.CustomSortComparer = new RowComparer(liberateGVColumn);
titleGVColumn.CustomSortComparer = new RowComparer(titleGVColumn);
authorsGVColumn.CustomSortComparer = new RowComparer(authorsGVColumn);
narratorsGVColumn.CustomSortComparer = new RowComparer(narratorsGVColumn);
lengthGVColumn.CustomSortComparer = new RowComparer(lengthGVColumn);
seriesGVColumn.CustomSortComparer = new RowComparer(seriesGVColumn);
descriptionGVColumn.CustomSortComparer = new RowComparer(descriptionGVColumn);
categoryGVColumn.CustomSortComparer = new RowComparer(categoryGVColumn);
productRatingGVColumn.CustomSortComparer = new RowComparer(productRatingGVColumn);
purchaseDateGVColumn.CustomSortComparer = new RowComparer(purchaseDateGVColumn);
myRatingGVColumn.CustomSortComparer = new RowComparer(myRatingGVColumn);
miscGVColumn.CustomSortComparer = new RowComparer(miscGVColumn);
tagAndDetailsGVColumn.CustomSortComparer = new RowComparer(tagAndDetailsGVColumn);
removeGVColumn.PropertyChanged += RemoveGVColumn_PropertyChanged;
if (Design.IsDesignMode)
{
using var context = DbContexts.GetContext();
var book = context.GetLibraryBook_Flat_NoTracking("B017V4IM1G");
productsGrid.DataContext = _viewModel = new ProductsDisplayViewModel(new List<LibraryBook> { book });
return;
}
}
private void RemoveGVColumn_PropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e)
{
}
private static object tagObj = new();
private static readonly IBrush SeriesBgColor = Brush.Parse("#ffe6ffe6");
private void ProductsGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
if (e.Row.Tag == tagObj)
return;
e.Row.Tag = tagObj;
static IBrush GetRowColor(DataGridRow row)
=> row.DataContext is GridEntry2 gEntry
&& gEntry is LibraryBookEntry2 lbEntry
&& lbEntry.Parent is not null
? SeriesBgColor
: null;
e.Row.Background = GetRowColor(e.Row);
e.Row.DataContextChanged += (sender, e) =>
{
var row = sender as DataGridRow;
row.Background = GetRowColor(row);
};
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
@ -69,6 +147,12 @@ namespace LibationWinForms.AvaloniaUI.Views
public string PropertyName { get; init; }
public ListSortDirection? SortDirection { get; set; }
public RowComparer(DataGridColumn column)
{
Column = column;
PropertyName = column.SortMemberPath;
}
/// <summary>
/// This compare method 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
@ -137,24 +221,15 @@ namespace LibationWinForms.AvaloniaUI.Views
}
}
Dictionary<DataGridColumn, RowComparer> ColumnComparers = new();
DataGridColumn CurrentSortColumn;
private void Dg1_Sorting(object sender, DataGridColumnEventArgs e)
{
if (!ColumnComparers.ContainsKey(e.Column))
ColumnComparers[e.Column] = new RowComparer
{
Column = e.Column,
PropertyName = e.Column.SortMemberPath
};
var comparer = e.Column.CustomSortComparer as RowComparer;
//Force the comparer to get the current sort order. We can't
//retrieve it from inside this event handler because Avalonia
//doesn't set the property until after this event.
ColumnComparers[e.Column].SortDirection = null;
e.Column.CustomSortComparer = ColumnComparers[e.Column];
comparer.SortDirection = null;
CurrentSortColumn = e.Column;
}
@ -391,8 +466,8 @@ namespace LibationWinForms.AvaloniaUI.Views
//In Avalonia, if you fire PropertyChanged with an empty or invalid property name, nothing is updated.
//So we must notify for specific properties that we believed changed.
removed.Parent.NotifyPropertyChanged(nameof(SeriesEntrys2.Length));
removed.Parent.NotifyPropertyChanged(nameof(SeriesEntrys2.PurchaseDate));
removed.Parent.RaisePropertyChanged(nameof(SeriesEntrys2.Length));
removed.Parent.RaisePropertyChanged(nameof(SeriesEntrys2.PurchaseDate));
}
//Remove series that have no children
@ -466,8 +541,8 @@ namespace LibationWinForms.AvaloniaUI.Views
else
bindingList.CollapseItem(seriesEntry);
seriesEntry.NotifyPropertyChanged(nameof(SeriesEntrys2.Length));
seriesEntry.NotifyPropertyChanged(nameof(SeriesEntrys2.PurchaseDate));
seriesEntry.RaisePropertyChanged(nameof(SeriesEntrys2.Length));
seriesEntry.RaisePropertyChanged(nameof(SeriesEntrys2.PurchaseDate));
}
else
existingEpisodeEntry.UpdateLibraryBook(episodeBook);
@ -493,7 +568,9 @@ namespace LibationWinForms.AvaloniaUI.Views
if (CurrentSortColumn is null)
bindingList.InternalList.Sort((i1, i2) => i2.DateAdded.CompareTo(i1.DateAdded));
else
CurrentSortColumn?.Sort(ColumnComparers[CurrentSortColumn].SortDirection.Value);
{
CurrentSortColumn.Sort(((RowComparer)CurrentSortColumn.CustomSortComparer).SortDirection ?? ListSortDirection.Ascending);
}
bindingList.ResetCollection();
}