diff --git a/Source/LibationUiBase/ReactiveObject.cs b/Source/LibationUiBase/ReactiveObject.cs index e86ed991..53392311 100644 --- a/Source/LibationUiBase/ReactiveObject.cs +++ b/Source/LibationUiBase/ReactiveObject.cs @@ -7,8 +7,14 @@ using System.Runtime.CompilerServices; #nullable enable namespace LibationUiBase; +/// +/// ReactiveObject is the base object for ViewModel classes, and it implements INotifyPropertyChanging +/// and INotifyPropertyChanged. Additionally +/// object changes. +/// public class ReactiveObject : SynchronizeInvoker, INotifyPropertyChanged, INotifyPropertyChanging { + // see also notes in Libation/Source/_ARCHITECTURE NOTES.txt :: MVVM public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangingEventHandler? PropertyChanging; diff --git a/Source/LibationUiBase/SeriesView/AyceButton.cs b/Source/LibationUiBase/SeriesView/AyceButton.cs index 263e6773..00fb2403 100644 --- a/Source/LibationUiBase/SeriesView/AyceButton.cs +++ b/Source/LibationUiBase/SeriesView/AyceButton.cs @@ -117,7 +117,7 @@ namespace LibationUiBase.SeriesView } private void DownloadButton_ButtonEnabled(object sender, EventArgs e) - => OnPropertyChanged(nameof(Enabled)); + => RaisePropertyChanged(nameof(Enabled)); public override int CompareTo(object ob) { diff --git a/Source/LibationUiBase/SeriesView/SeriesButton.cs b/Source/LibationUiBase/SeriesView/SeriesButton.cs index 3156c036..94d79f2d 100644 --- a/Source/LibationUiBase/SeriesView/SeriesButton.cs +++ b/Source/LibationUiBase/SeriesView/SeriesButton.cs @@ -1,8 +1,6 @@ using AudibleApi.Common; using DataLayer; -using Dinah.Core.Threading; using System; -using System.ComponentModel; using System.Threading.Tasks; namespace LibationUiBase.SeriesView @@ -10,11 +8,9 @@ namespace LibationUiBase.SeriesView /// /// base view model for the Series Viewer 'Availability' button column /// - public abstract class SeriesButton : SynchronizeInvoker, IComparable, INotifyPropertyChanged + public abstract class SeriesButton : ReactiveObject, IComparable { - public event PropertyChangedEventHandler PropertyChanged; private bool inLibrary; - protected Item Item { get; } public abstract string DisplayText { get; } public abstract bool HasButtonAction { get; } @@ -27,8 +23,8 @@ namespace LibationUiBase.SeriesView if (inLibrary != value) { inLibrary = value; - OnPropertyChanged(nameof(InLibrary)); - OnPropertyChanged(nameof(DisplayText)); + RaisePropertyChanged(nameof(InLibrary)); + RaisePropertyChanged(nameof(DisplayText)); } } } @@ -41,9 +37,6 @@ namespace LibationUiBase.SeriesView public abstract Task PerformClickAsync(LibraryBook accountBook); - protected void OnPropertyChanged(string propertyName) - => Invoke(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName))); - public override string ToString() => DisplayText; public abstract int CompareTo(object ob); diff --git a/Source/LibationUiBase/SeriesView/SeriesItem.cs b/Source/LibationUiBase/SeriesView/SeriesItem.cs index 44b451e4..cd7d19e1 100644 --- a/Source/LibationUiBase/SeriesView/SeriesItem.cs +++ b/Source/LibationUiBase/SeriesView/SeriesItem.cs @@ -4,7 +4,6 @@ using AudibleApi.Common; using AudibleUtilities; using DataLayer; using Dinah.Core; -using Dinah.Core.Threading; using FileLiberator; using LibationFileManager; using System.Collections.Generic; @@ -15,7 +14,7 @@ using System.Threading.Tasks; namespace LibationUiBase.SeriesView { - public class SeriesItem : SynchronizeInvoker, INotifyPropertyChanged + public class SeriesItem : ReactiveObject { public object Cover { get; private set; } public SeriesOrder Order { get; } @@ -23,8 +22,6 @@ namespace LibationUiBase.SeriesView public SeriesButton Button { get; } public Item Item { get; } - public event PropertyChangedEventHandler PropertyChanged; - private SeriesItem(Item item, string order, bool inLibrary, bool inWishList) { Item = item; @@ -42,10 +39,7 @@ namespace LibationUiBase.SeriesView } private void DownloadButton_PropertyChanged(object sender, PropertyChangedEventArgs e) - => OnPropertyChanged(nameof(Button)); - - private void OnPropertyChanged(string propertyName) - => Invoke(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName))); + => RaisePropertyChanged(nameof(Button)); private void LoadCover(string pictureId) { @@ -66,7 +60,7 @@ namespace LibationUiBase.SeriesView { Cover = BaseUtil.LoadImage(e.Picture, PictureSize._80x80); PictureStorage.PictureCached -= PictureStorage_PictureCached; - OnPropertyChanged(nameof(Cover)); + RaisePropertyChanged(nameof(Cover)); } } } diff --git a/Source/LibationUiBase/SeriesView/WishlistButton.cs b/Source/LibationUiBase/SeriesView/WishlistButton.cs index fcf4bcb8..8a236165 100644 --- a/Source/LibationUiBase/SeriesView/WishlistButton.cs +++ b/Source/LibationUiBase/SeriesView/WishlistButton.cs @@ -22,14 +22,7 @@ namespace LibationUiBase.SeriesView public override bool Enabled { get => instanceEnabled; - protected set - { - if (instanceEnabled != value) - { - instanceEnabled = value; - OnPropertyChanged(nameof(Enabled)); - } - } + protected set => RaiseAndSetIfChanged(ref instanceEnabled, value); } private bool InWishList @@ -40,8 +33,8 @@ namespace LibationUiBase.SeriesView if (inWishList != value) { inWishList = value; - OnPropertyChanged(nameof(InWishList)); - OnPropertyChanged(nameof(DisplayText)); + RaisePropertyChanged(nameof(InWishList)); + RaisePropertyChanged(nameof(DisplayText)); } } } diff --git a/Source/LibationWinForms/Dialogs/BookRecordsDialog.cs b/Source/LibationWinForms/Dialogs/BookRecordsDialog.cs index a93e652e..2891f7ac 100644 --- a/Source/LibationWinForms/Dialogs/BookRecordsDialog.cs +++ b/Source/LibationWinForms/Dialogs/BookRecordsDialog.cs @@ -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 bool _ischecked; 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 Start => formatTimeSpan(Record.Start); public string Created => Record.Created.ToString(DateFormat); diff --git a/Source/LibationWinForms/GridView/AsyncNotifyPropertyChanged.cs b/Source/LibationWinForms/GridView/AsyncNotifyPropertyChanged.cs deleted file mode 100644 index f02dd26e..00000000 --- a/Source/LibationWinForms/GridView/AsyncNotifyPropertyChanged.cs +++ /dev/null @@ -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))); - } -} diff --git a/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.Designer.cs b/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.Designer.cs index 85fdb856..b5bf91f5 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.Designer.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.Designer.cs @@ -40,7 +40,6 @@ this.runningTimeLbl = new System.Windows.Forms.ToolStripStatusLabel(); this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPage1 = new System.Windows.Forms.TabPage(); - this.panel3 = new System.Windows.Forms.Panel(); this.virtualFlowControl2 = new LibationWinForms.ProcessQueue.VirtualFlowControl(); this.panel1 = new System.Windows.Forms.Panel(); this.label1 = new System.Windows.Forms.Label(); @@ -134,7 +133,6 @@ // // tabPage1 // - this.tabPage1.Controls.Add(this.panel3); this.tabPage1.Controls.Add(this.virtualFlowControl2); this.tabPage1.Controls.Add(this.panel1); this.tabPage1.Location = new System.Drawing.Point(4, 24); @@ -145,14 +143,6 @@ this.tabPage1.Text = "Process Queue"; 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 // this.virtualFlowControl2.AccessibleRole = System.Windows.Forms.AccessibleRole.None; @@ -174,14 +164,14 @@ this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom; this.panel1.Location = new System.Drawing.Point(3, 427); 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; // // label1 // this.label1.Anchor = System.Windows.Forms.AnchorStyles.Right; 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.Size = new System.Drawing.Size(54, 15); this.label1.TabIndex = 5; @@ -196,7 +186,7 @@ 0, 0, 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[] { 999, 0, @@ -348,7 +338,6 @@ this.panel2.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); - } #endregion @@ -367,7 +356,6 @@ private System.Windows.Forms.ToolStripStatusLabel queueNumberLbl; private System.Windows.Forms.ToolStripStatusLabel completedNumberLbl; private System.Windows.Forms.ToolStripStatusLabel errorNumberLbl; - private System.Windows.Forms.Panel panel3; private System.Windows.Forms.Panel panel4; private System.Windows.Forms.ToolStripStatusLabel runningTimeLbl; private System.Windows.Forms.DataGridView logDGV; diff --git a/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs b/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs index 76a7d43d..15bcc5d6 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs @@ -1,5 +1,4 @@ -using LibationFileManager; -using LibationUiBase; +using LibationUiBase; using LibationUiBase.ProcessQueue; using System; using System.ComponentModel; @@ -35,23 +34,18 @@ internal partial class ProcessQueueControl : UserControl ViewModel.PropertyChanged += ProcessQueue_PropertyChanged; ViewModel.LogEntries.CollectionChanged += LogEntries_CollectionChanged; + ProcessQueue_PropertyChanged(this, new PropertyChangedEventArgs(null)); } private void LogEntries_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (!IsDisposed && e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) { - foreach(var entry in e.NewItems?.OfType() ?? []) + foreach (var entry in e.NewItems?.OfType() ?? []) logDGV.Rows.Add(entry.LogDate, entry.LogMessage); } } - protected override void OnLoad(EventArgs e) - { - if (DesignMode) return; - ProcessQueue_PropertyChanged(this, new PropertyChangedEventArgs(null)); - } - private async void cancelAllBtn_Click(object? sender, EventArgs e) { ViewModel.Queue.ClearQueue(); @@ -155,7 +149,7 @@ internal partial class ProcessQueueControl : UserControl ViewModel.Queue.MoveQueuePosition(item, position.Value); } } - catch(Exception ex) + catch (Exception ex) { Serilog.Log.Logger.Error(ex, "Error handling button click from queued item"); }