Use LibationUiBase.ReactiveObject where applicable

Also tweak the classic process queue control layout
This commit is contained in:
Michael Bucari-Tovo 2025-07-22 11:59:34 -06:00
parent 0f7ffacdf8
commit 0f4197924e
9 changed files with 25 additions and 74 deletions

View File

@ -7,8 +7,14 @@ using System.Runtime.CompilerServices;
#nullable enable #nullable enable
namespace LibationUiBase; namespace LibationUiBase;
/// <summary>
/// ReactiveObject is the base object for ViewModel classes, and it implements INotifyPropertyChanging
/// and INotifyPropertyChanged. Additionally
/// object changes.
/// </summary>
public class ReactiveObject : SynchronizeInvoker, INotifyPropertyChanged, INotifyPropertyChanging public class ReactiveObject : SynchronizeInvoker, INotifyPropertyChanged, INotifyPropertyChanging
{ {
// see also notes in Libation/Source/_ARCHITECTURE NOTES.txt :: MVVM
public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangedEventHandler? PropertyChanged;
public event PropertyChangingEventHandler? PropertyChanging; public event PropertyChangingEventHandler? PropertyChanging;

View File

@ -117,7 +117,7 @@ namespace LibationUiBase.SeriesView
} }
private void DownloadButton_ButtonEnabled(object sender, EventArgs e) private void DownloadButton_ButtonEnabled(object sender, EventArgs e)
=> OnPropertyChanged(nameof(Enabled)); => RaisePropertyChanged(nameof(Enabled));
public override int CompareTo(object ob) public override int CompareTo(object ob)
{ {

View File

@ -1,8 +1,6 @@
using AudibleApi.Common; using AudibleApi.Common;
using DataLayer; using DataLayer;
using Dinah.Core.Threading;
using System; using System;
using System.ComponentModel;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LibationUiBase.SeriesView namespace LibationUiBase.SeriesView
@ -10,11 +8,9 @@ namespace LibationUiBase.SeriesView
/// <summary> /// <summary>
/// base view model for the Series Viewer 'Availability' button column /// base view model for the Series Viewer 'Availability' button column
/// </summary> /// </summary>
public abstract class SeriesButton : SynchronizeInvoker, IComparable, INotifyPropertyChanged public abstract class SeriesButton : ReactiveObject, IComparable
{ {
public event PropertyChangedEventHandler PropertyChanged;
private bool inLibrary; private bool inLibrary;
protected Item Item { get; } protected Item Item { get; }
public abstract string DisplayText { get; } public abstract string DisplayText { get; }
public abstract bool HasButtonAction { get; } public abstract bool HasButtonAction { get; }
@ -27,8 +23,8 @@ namespace LibationUiBase.SeriesView
if (inLibrary != value) if (inLibrary != value)
{ {
inLibrary = value; inLibrary = value;
OnPropertyChanged(nameof(InLibrary)); RaisePropertyChanged(nameof(InLibrary));
OnPropertyChanged(nameof(DisplayText)); RaisePropertyChanged(nameof(DisplayText));
} }
} }
} }
@ -41,9 +37,6 @@ namespace LibationUiBase.SeriesView
public abstract Task PerformClickAsync(LibraryBook accountBook); public abstract Task PerformClickAsync(LibraryBook accountBook);
protected void OnPropertyChanged(string propertyName)
=> Invoke(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)));
public override string ToString() => DisplayText; public override string ToString() => DisplayText;
public abstract int CompareTo(object ob); public abstract int CompareTo(object ob);

View File

@ -4,7 +4,6 @@ using AudibleApi.Common;
using AudibleUtilities; using AudibleUtilities;
using DataLayer; using DataLayer;
using Dinah.Core; using Dinah.Core;
using Dinah.Core.Threading;
using FileLiberator; using FileLiberator;
using LibationFileManager; using LibationFileManager;
using System.Collections.Generic; using System.Collections.Generic;
@ -15,7 +14,7 @@ using System.Threading.Tasks;
namespace LibationUiBase.SeriesView namespace LibationUiBase.SeriesView
{ {
public class SeriesItem : SynchronizeInvoker, INotifyPropertyChanged public class SeriesItem : ReactiveObject
{ {
public object Cover { get; private set; } public object Cover { get; private set; }
public SeriesOrder Order { get; } public SeriesOrder Order { get; }
@ -23,8 +22,6 @@ namespace LibationUiBase.SeriesView
public SeriesButton Button { get; } public SeriesButton Button { get; }
public Item Item { get; } public Item Item { get; }
public event PropertyChangedEventHandler PropertyChanged;
private SeriesItem(Item item, string order, bool inLibrary, bool inWishList) private SeriesItem(Item item, string order, bool inLibrary, bool inWishList)
{ {
Item = item; Item = item;
@ -42,10 +39,7 @@ namespace LibationUiBase.SeriesView
} }
private void DownloadButton_PropertyChanged(object sender, PropertyChangedEventArgs e) private void DownloadButton_PropertyChanged(object sender, PropertyChangedEventArgs e)
=> OnPropertyChanged(nameof(Button)); => RaisePropertyChanged(nameof(Button));
private void OnPropertyChanged(string propertyName)
=> Invoke(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)));
private void LoadCover(string pictureId) private void LoadCover(string pictureId)
{ {
@ -66,7 +60,7 @@ namespace LibationUiBase.SeriesView
{ {
Cover = BaseUtil.LoadImage(e.Picture, PictureSize._80x80); Cover = BaseUtil.LoadImage(e.Picture, PictureSize._80x80);
PictureStorage.PictureCached -= PictureStorage_PictureCached; PictureStorage.PictureCached -= PictureStorage_PictureCached;
OnPropertyChanged(nameof(Cover)); RaisePropertyChanged(nameof(Cover));
} }
} }
} }

View File

@ -22,14 +22,7 @@ namespace LibationUiBase.SeriesView
public override bool Enabled public override bool Enabled
{ {
get => instanceEnabled; get => instanceEnabled;
protected set protected set => RaiseAndSetIfChanged(ref instanceEnabled, value);
{
if (instanceEnabled != value)
{
instanceEnabled = value;
OnPropertyChanged(nameof(Enabled));
}
}
} }
private bool InWishList private bool InWishList
@ -40,8 +33,8 @@ namespace LibationUiBase.SeriesView
if (inWishList != value) if (inWishList != value)
{ {
inWishList = value; inWishList = value;
OnPropertyChanged(nameof(InWishList)); RaisePropertyChanged(nameof(InWishList));
OnPropertyChanged(nameof(DisplayText)); RaisePropertyChanged(nameof(DisplayText));
} }
} }
} }

View File

@ -250,12 +250,12 @@ namespace LibationWinForms.Dialogs
} }
} }
private class BookRecordEntry : GridView.AsyncNotifyPropertyChanged private class BookRecordEntry : LibationUiBase.ReactiveObject
{ {
private const string DateFormat = "yyyy-MM-dd HH\\:mm"; private const string DateFormat = "yyyy-MM-dd HH\\:mm";
private bool _ischecked; private bool _ischecked;
public IRecord Record { get; } public IRecord Record { get; }
public bool IsChecked { get => _ischecked; set { _ischecked = value; NotifyPropertyChanged(); } } public bool IsChecked { get => _ischecked; set => RaiseAndSetIfChanged(ref _ischecked, value); }
public string Type => Record.GetType().Name; public string Type => Record.GetType().Name;
public string Start => formatTimeSpan(Record.Start); public string Start => formatTimeSpan(Record.Start);
public string Created => Record.Created.ToString(DateFormat); public string Created => Record.Created.ToString(DateFormat);

View File

@ -1,17 +0,0 @@
using Dinah.Core.Threading;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace LibationWinForms.GridView
{
public abstract class AsyncNotifyPropertyChanged : SynchronizeInvoker, INotifyPropertyChanged
{
// see also notes in Libation/Source/_ARCHITECTURE NOTES.txt :: MVVM
public event PropertyChangedEventHandler PropertyChanged;
// per standard INotifyPropertyChanged pattern:
// https://docs.microsoft.com/en-us/dotnet/desktop/wpf/data/how-to-implement-property-change-notification
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
=> this.UIThreadSync(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)));
}
}

View File

@ -40,7 +40,6 @@
this.runningTimeLbl = new System.Windows.Forms.ToolStripStatusLabel(); this.runningTimeLbl = new System.Windows.Forms.ToolStripStatusLabel();
this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage(); this.tabPage1 = new System.Windows.Forms.TabPage();
this.panel3 = new System.Windows.Forms.Panel();
this.virtualFlowControl2 = new LibationWinForms.ProcessQueue.VirtualFlowControl(); this.virtualFlowControl2 = new LibationWinForms.ProcessQueue.VirtualFlowControl();
this.panel1 = new System.Windows.Forms.Panel(); this.panel1 = new System.Windows.Forms.Panel();
this.label1 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label();
@ -134,7 +133,6 @@
// //
// tabPage1 // tabPage1
// //
this.tabPage1.Controls.Add(this.panel3);
this.tabPage1.Controls.Add(this.virtualFlowControl2); this.tabPage1.Controls.Add(this.virtualFlowControl2);
this.tabPage1.Controls.Add(this.panel1); this.tabPage1.Controls.Add(this.panel1);
this.tabPage1.Location = new System.Drawing.Point(4, 24); this.tabPage1.Location = new System.Drawing.Point(4, 24);
@ -145,14 +143,6 @@
this.tabPage1.Text = "Process Queue"; this.tabPage1.Text = "Process Queue";
this.tabPage1.UseVisualStyleBackColor = true; this.tabPage1.UseVisualStyleBackColor = true;
// //
// panel3
//
this.panel3.Dock = System.Windows.Forms.DockStyle.Bottom;
this.panel3.Location = new System.Drawing.Point(3, 422);
this.panel3.Name = "panel3";
this.panel3.Size = new System.Drawing.Size(390, 5);
this.panel3.TabIndex = 4;
//
// virtualFlowControl2 // virtualFlowControl2
// //
this.virtualFlowControl2.AccessibleRole = System.Windows.Forms.AccessibleRole.None; this.virtualFlowControl2.AccessibleRole = System.Windows.Forms.AccessibleRole.None;
@ -174,14 +164,14 @@
this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom; this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom;
this.panel1.Location = new System.Drawing.Point(3, 427); this.panel1.Location = new System.Drawing.Point(3, 427);
this.panel1.Name = "panel1"; this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(390, 25); this.panel1.Size = new System.Drawing.Size(390, 29);
this.panel1.TabIndex = 2; this.panel1.TabIndex = 2;
// //
// label1 // label1
// //
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Right; this.label1.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label1.AutoSize = true; this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(148, 4); this.label1.Location = new System.Drawing.Point(148, 6);
this.label1.Name = "label1"; this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(54, 15); this.label1.Size = new System.Drawing.Size(54, 15);
this.label1.TabIndex = 5; this.label1.TabIndex = 5;
@ -196,7 +186,7 @@
0, 0,
0, 0,
65536}); 65536});
this.numericUpDown1.Location = new System.Drawing.Point(208, 0); this.numericUpDown1.Location = new System.Drawing.Point(208, 2);
this.numericUpDown1.Maximum = new decimal(new int[] { this.numericUpDown1.Maximum = new decimal(new int[] {
999, 999,
0, 0,
@ -348,7 +338,6 @@
this.panel2.ResumeLayout(false); this.panel2.ResumeLayout(false);
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
} }
#endregion #endregion
@ -367,7 +356,6 @@
private System.Windows.Forms.ToolStripStatusLabel queueNumberLbl; private System.Windows.Forms.ToolStripStatusLabel queueNumberLbl;
private System.Windows.Forms.ToolStripStatusLabel completedNumberLbl; private System.Windows.Forms.ToolStripStatusLabel completedNumberLbl;
private System.Windows.Forms.ToolStripStatusLabel errorNumberLbl; private System.Windows.Forms.ToolStripStatusLabel errorNumberLbl;
private System.Windows.Forms.Panel panel3;
private System.Windows.Forms.Panel panel4; private System.Windows.Forms.Panel panel4;
private System.Windows.Forms.ToolStripStatusLabel runningTimeLbl; private System.Windows.Forms.ToolStripStatusLabel runningTimeLbl;
private System.Windows.Forms.DataGridView logDGV; private System.Windows.Forms.DataGridView logDGV;

View File

@ -1,5 +1,4 @@
using LibationFileManager; using LibationUiBase;
using LibationUiBase;
using LibationUiBase.ProcessQueue; using LibationUiBase.ProcessQueue;
using System; using System;
using System.ComponentModel; using System.ComponentModel;
@ -35,6 +34,7 @@ internal partial class ProcessQueueControl : UserControl
ViewModel.PropertyChanged += ProcessQueue_PropertyChanged; ViewModel.PropertyChanged += ProcessQueue_PropertyChanged;
ViewModel.LogEntries.CollectionChanged += LogEntries_CollectionChanged; ViewModel.LogEntries.CollectionChanged += LogEntries_CollectionChanged;
ProcessQueue_PropertyChanged(this, new PropertyChangedEventArgs(null));
} }
private void LogEntries_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) private void LogEntries_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
@ -46,12 +46,6 @@ internal partial class ProcessQueueControl : UserControl
} }
} }
protected override void OnLoad(EventArgs e)
{
if (DesignMode) return;
ProcessQueue_PropertyChanged(this, new PropertyChangedEventArgs(null));
}
private async void cancelAllBtn_Click(object? sender, EventArgs e) private async void cancelAllBtn_Click(object? sender, EventArgs e)
{ {
ViewModel.Queue.ClearQueue(); ViewModel.Queue.ClearQueue();