diff --git a/UI/ViewModels/HierarchyTreeViewModel.cs b/UI/ViewModels/HierarchyTreeViewModel.cs index 5a8e03d..6fbc333 100644 --- a/UI/ViewModels/HierarchyTreeViewModel.cs +++ b/UI/ViewModels/HierarchyTreeViewModel.cs @@ -8,7 +8,7 @@ using TagHierarchyManager.Models; namespace TagHierarchyManager.UI.ViewModels; -public partial class HierarchyTreeViewModel : ViewModelBase +public partial class HierarchyTreeViewModel : ViewModelBase, IDisposable { private readonly MainWindowViewModel _mainWindow; private readonly Dictionary _viewModelMap = new(); @@ -28,11 +28,34 @@ public partial class HierarchyTreeViewModel : ViewModelBase { this._mainWindow = mainWindow; - // this is a bit naive, but it works lol - this._mainWindow.Database.TagUpdated += (_, _) => Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(OnTreeUpdate); - this._mainWindow.Database.TagAdded += (_, _) => Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(OnTreeUpdate); - // TODO delete the single tag, don't resync hierarchy. should make it snappier and more manageable. - this._mainWindow.Database.TagDeleted += (_, _) => Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(OnTreeUpdate); + // TODO proper methods here so it can be unsubscribed. + this.SubscribeToEvents(); + } + + // TODO unsubscribe, if necessary. + private void SubscribeToEvents() + { + this._mainWindow.Database.TagUpdated += TagDatabase_OnTagUpdated; + this._mainWindow.Database.TagAdded += TagDatabase_OnTagAdded; + this._mainWindow.Database.TagDeleted += TagDatabase_OnTagDeleted; + } + + private void TagDatabase_OnTagUpdated(object? sender, Tag _) => + Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(OnTreeUpdate); + + private void TagDatabase_OnTagAdded(object? sender, Tag _) => + Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(OnTreeUpdate); + + private void TagDatabase_OnTagDeleted(object? sender, (int id, string name) _) => + Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(OnTreeUpdate); + + public void Dispose() + { + this._mainWindow.Database.TagUpdated -= TagDatabase_OnTagUpdated; + this._mainWindow.Database.TagAdded -= TagDatabase_OnTagAdded; + this._mainWindow.Database.TagDeleted -= TagDatabase_OnTagDeleted; + + _viewModelMap.Clear(); } public async Task InitializeAsync() diff --git a/UI/ViewModels/MainWindowViewModel.cs b/UI/ViewModels/MainWindowViewModel.cs index 6362d02..cb39e61 100644 --- a/UI/ViewModels/MainWindowViewModel.cs +++ b/UI/ViewModels/MainWindowViewModel.cs @@ -147,7 +147,7 @@ public partial class MainWindowViewModel : ViewModelBase { this.IsDbLoaded = false; TagDatabase db = new(); - db.InitialisationComplete += OnDatabaseLoaded; + db.InitialisationComplete += this.TagDatabase_OnInitalisationComplete; await db.LoadAsync(filePath); } @@ -163,18 +163,20 @@ public partial class MainWindowViewModel : ViewModelBase this.UnsavedChanges = false; } - private void OnDatabaseLoaded(object sender, EventArgs e) + private void TagDatabase_OnInitalisationComplete(object sender, EventArgs e) { if (sender is not TagDatabase db) return; Avalonia.Threading.Dispatcher.UIThread.Post(async () => { + (this.HierarchyTreeViewModel as IDisposable)?.Dispose(); + this.Database = db; this.IsDbLoaded = true; this.HierarchyTreeViewModel = new HierarchyTreeViewModel(this); await this.HierarchyTreeViewModel.InitializeAsync(); this.OnPropertyChanged(nameof(TotalTags)); this.OnPropertyChanged(nameof(WindowTitle)); - this.Database.InitialisationComplete -= OnDatabaseLoaded; + this.Database.InitialisationComplete -= this.TagDatabase_OnInitalisationComplete; this.StatusBlockText = string.Format(Resources.StatusBlockDbLoadSuccessful, this.Database.Name); }); Debug.WriteLine($"Database loaded on UI - name: {db.Name}, version: {db.Version}");