Use ReactiveUI.
Sort of fix remove book checkbox column.
This commit is contained in:
parent
5f45d28b9f
commit
6e091230cf
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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];
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -121,17 +109,17 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
|
||||
{
|
||||
case nameof(udi.Tags):
|
||||
Book.UserDefinedItem.Tags = udi.Tags;
|
||||
NotifyPropertyChanged(nameof(BookTags));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -7,19 +7,14 @@ 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)
|
||||
@ -31,7 +26,6 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
|
||||
LogMessage = text.Trim()
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class LogEntry
|
||||
@ -40,5 +34,4 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
|
||||
public string LogDateString => LogDate.ToShortTimeString();
|
||||
public string LogMessage { get; init; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -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}"/>
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user