Dispose everything in Controls
MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/CoinJoinTabViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/CoinJoinTabViewModel.cs
@@ -23,10 +23,8 @@ using static WalletWasabi.Models.ServiceConfiguration;
namespace WalletWasabi.Gui.Controls.WalletExplorer
{
- public class CoinJoinTabViewModel : WalletActionViewModel, IDisposable
+ public class CoinJoinTabViewModel : WalletActionViewModel
{
- private CompositeDisposable Disposables { get; }
-
private CoinListViewModel _coinsList;
private long _roundId;
private int _successfulRoundCount;
@@ -50,8 +48,6 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
public CoinJoinTabViewModel(WalletViewModel walletViewModel)
: base("CoinJoin", walletViewModel)
{
- Disposables = new CompositeDisposable();
-
Password = "";
TargetPrivacy = GetTargetPrivacy(Global.Config.MixUntilAnonymitySet);
@@ -516,9 +512,7 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
#region IDisposable Support
- private volatile bool _disposedValue = false; // To detect redundant calls
-
- protected virtual void Dispose(bool disposing)
+ protected override void Dispose(bool disposing)
{
if (!_disposedValue)
{
@@ -535,23 +529,14 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
{
_coinsList.DequeueCoinsPressed -= CoinsList_DequeueCoinsPressedAsync;
}
-
- Disposables?.Dispose();
- CoinsList?.Dispose();
}
- CoinsList = null;
+ base.Dispose(disposing);
+
_disposedValue = true;
}
}
- // This code added to correctly implement the disposable pattern.
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
- Dispose(true);
- }
-
#endregion IDisposable Support
}
}

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/CoinListViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/CoinListViewModel.cs
@@ -430,10 +430,8 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
if (cvm != null)
{
cvm.PropertyChanged -= Coin_PropertyChanged;
- cvm?.Dispose();
}
}
- RootList?.Dispose();
}
if (RemovedCoinViewModels != null)
@@ -443,7 +441,6 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
if (cvm != null)
{
cvm.PropertyChanged -= Coin_PropertyChanged;
- cvm?.Dispose();
}
}
}

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/HistoryTabViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/HistoryTabViewModel.cs
@@ -20,10 +20,8 @@ using WalletWasabi.Services;
namespace WalletWasabi.Gui.Controls.WalletExplorer
{
- public class HistoryTabViewModel : WalletActionViewModel, IDisposable
+ public class HistoryTabViewModel : WalletActionViewModel
{
- private CompositeDisposable Disposables { get; }
-
private ObservableCollection<TransactionViewModel> _transactions;
private TransactionViewModel _selectedTransaction;
private SortOrder _dateSortDirection;
@@ -35,8 +33,6 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
public HistoryTabViewModel(WalletViewModel walletViewModel)
: base("History", walletViewModel)
{
- Disposables = new CompositeDisposable();
-
Transactions = new ObservableCollection<TransactionViewModel>();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
RewriteTableAsync();
@@ -291,32 +287,5 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
}
}
}
-
- #region IDisposable Support
-
- private volatile bool _disposedValue = false; // To detect redundant calls
-
- protected virtual void Dispose(bool disposing)
- {
- if (!_disposedValue)
- {
- if (disposing)
- {
- Disposables?.Dispose();
- }
-
- _transactions = null;
- _disposedValue = true;
- }
- }
-
- // This code added to correctly implement the disposable pattern.
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
- Dispose(true);
- }
-
- #endregion IDisposable Support
}
}

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/ReceiveTabViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/ReceiveTabViewModel.cs
@@ -15,7 +15,7 @@ using WalletWasabi.KeyManagement;
namespace WalletWasabi.Gui.Controls.WalletExplorer
{
- public class ReceiveTabViewModel : WalletActionViewModel, IDisposable
+ public class ReceiveTabViewModel : WalletActionViewModel
{
private ObservableCollection<AddressViewModel> _addresses;
private AddressViewModel _selectedAddress;
@@ -24,12 +24,10 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
private bool _labelRequiredNotificationVisible;
private int _caretIndex;
private ObservableCollection<SuggestionViewModel> _suggestions;
- private CompositeDisposable Disposables { get; }
public ReceiveTabViewModel(WalletViewModel walletViewModel)
: base("Receive", walletViewModel)
{
- Disposables = new CompositeDisposable();
_addresses = new ObservableCollection<AddressViewModel>();
Label = "";
@@ -207,34 +205,5 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
}
public ReactiveCommand GenerateCommand { get; }
-
- #region IDisposable Support
-
- private volatile bool _disposedValue = false; // To detect redundant calls
-
- protected virtual void Dispose(bool disposing)
- {
- if (!_disposedValue)
- {
- if (disposing)
- {
- Disposables?.Dispose();
- }
-
- _addresses = null;
- _suggestions = null;
-
- _disposedValue = true;
- }
- }
-
- // This code added to correctly implement the disposable pattern.
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
- Dispose(true);
- }
-
- #endregion IDisposable Support
}
}

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/SendTabViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/SendTabViewModel.cs
@@ -23,7 +23,7 @@ using System.Reactive.Disposables;
namespace WalletWasabi.Gui.Controls.WalletExplorer
{
- public class SendTabViewModel : WalletActionViewModel, IDisposable
+ public class SendTabViewModel : WalletActionViewModel
{
private CoinListViewModel _coinList;
private string _buildTransactionButtonText;
@@ -56,7 +56,6 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
private int _caretIndex;
private ObservableCollection<SuggestionViewModel> _suggestions;
private FeeDisplayFormat _feeDisplayFormat;
- private CompositeDisposable Disposables { get; }
private bool IgnoreAmountChanges { get; set; }
@@ -73,13 +72,12 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
public SendTabViewModel(WalletViewModel walletViewModel)
: base("Send", walletViewModel)
{
- Disposables = new CompositeDisposable();
Label = "";
AllSelectedAmount = Money.Zero;
UsdExchangeRate = Global.Synchronizer.UsdExchangeRate;
SetAmountWatermarkAndToolTip(Money.Zero);
- CoinList = new CoinListViewModel();
+ CoinList = new CoinListViewModel().DisposeWith(Disposables);
BuildTransactionButtonText = BuildTransactionButtonTextString;
@@ -908,9 +906,7 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
#region IDisposable Support
- private volatile bool _disposedValue = false; // To detect redundant calls
-
- protected virtual void Dispose(bool disposing)
+ protected override void Dispose(bool disposing)
{
if (!_disposedValue)
{
@@ -925,25 +921,15 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
{
_coinList.SelectionChanged -= CoinList_SelectionChanged;
_coinList.DequeueCoinsPressed -= CoinsList_DequeueCoinsPressedAsync;
- _coinList.Dispose();
}
-
- Disposables?.Dispose();
}
- CoinList = null;
+ base.Dispose(disposing);
_disposedValue = true;
}
}
- // This code added to correctly implement the disposable pattern.
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
- Dispose(true);
- }
-
#endregion IDisposable Support
}
}

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/TransactionViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/TransactionViewModel.cs
@@ -13,14 +13,16 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
{
public class TransactionViewModel : ViewModelBase, IDisposable
{
- private TransactionInfo _model;
private CompositeDisposable Disposables { get; }
+
+ private TransactionInfo _model;
private bool _clipboardNotificationVisible;
private double _clipboardNotificationOpacity;
public TransactionViewModel(TransactionInfo model)
{
Disposables = new CompositeDisposable();
+
_model = model;
ClipboardNotificationVisible = false;
ClipboardNotificationOpacity = 0;
@@ -99,7 +101,6 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
Disposables?.Dispose();
}
- _model = null;
_disposedValue = true;
}
}

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/WalletActionViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/WalletActionViewModel.cs
@@ -4,20 +4,25 @@ using AvalonStudio.Shell;
using ReactiveUI;
using System;
using System.Collections.Generic;
+using System.Reactive.Disposables;
using System.Text;
using WalletWasabi.Gui.ViewModels;
namespace WalletWasabi.Gui.Controls.WalletExplorer
{
- public class WalletActionViewModel : WasabiDocumentTabViewModel
+ public class WalletActionViewModel : WasabiDocumentTabViewModel, IDisposable
{
+ protected CompositeDisposable Disposables { get; }
+
public WalletViewModel Wallet { get; }
public WalletActionViewModel(string title, WalletViewModel walletViewModel)
: base(title)
{
+ Disposables = new CompositeDisposable();
+
Wallet = walletViewModel;
- DoItCommand = ReactiveCommand.Create(DisplayActionTab);
+ DoItCommand = ReactiveCommand.Create(DisplayActionTab).DisposeWith(Disposables);
}
public ReactiveCommand DoItCommand { get; }
@@ -26,5 +31,31 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
{
IoC.Get<IShell>().AddOrSelectDocument(this);
}
+
+ #region IDisposable Support
+
+ protected volatile bool _disposedValue = false; // To detect redundant calls
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposedValue)
+ {
+ if (disposing)
+ {
+ Disposables?.Dispose();
+ }
+
+ _disposedValue = true;
+ }
+ }
+
+ // This code added to correctly implement the disposable pattern.
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(true);
+ }
+
+ #endregion IDisposable Support
}
}

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/WalletExplorerViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/WalletExplorerViewModel.cs
@@ -11,6 +11,7 @@ using System.Linq;
using AvalonStudio.Shell;
using WalletWasabi.Services;
using System.IO;
+using System.Reactive.Disposables;
namespace WalletWasabi.Gui.Controls.WalletExplorer
{
@@ -18,12 +19,16 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
[Export]
[ExportToolControl]
[Shared]
- public class WalletExplorerViewModel : ToolViewModel, IActivatableExtension
+ public class WalletExplorerViewModel : ToolViewModel, IActivatableExtension, IDisposable
{
+ private CompositeDisposable Disposables { get; }
+
public override Location DefaultLocation => Location.Right;
public WalletExplorerViewModel()
{
+ Disposables = new CompositeDisposable();
+
Title = "Wallet Explorer";
_wallets = new ObservableCollection<WalletViewModel>();
@@ -51,7 +56,7 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
if (_wallets.Any(x => x.Title == walletName))
return;
- WalletViewModel walletViewModel = new WalletViewModel(walletService, receiveDominant);
+ WalletViewModel walletViewModel = new WalletViewModel(walletService, receiveDominant).DisposeWith(Disposables);
_wallets.Add(walletViewModel);
}
@@ -63,5 +68,31 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
{
IoC.Get<IShell>().MainPerspective.AddOrSelectTool(this);
}
+
+ #region IDisposable Support
+
+ private volatile bool _disposedValue = false; // To detect redundant calls
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposedValue)
+ {
+ if (disposing)
+ {
+ Disposables?.Dispose();
+ }
+
+ _disposedValue = true;
+ }
+ }
+
+ // This code added to correctly implement the disposable pattern.
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(true);
+ }
+
+ #endregion IDisposable Support
}
}

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/WalletInfoViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/WalletInfoViewModel.cs
@@ -16,7 +16,7 @@ using WalletWasabi.Services;
namespace WalletWasabi.Gui.Controls.WalletExplorer
{
- public class WalletInfoViewModel : WalletActionViewModel, IDisposable
+ public class WalletInfoViewModel : WalletActionViewModel
{
private string _password;
private string _extendedMasterPrivateKey;
@@ -24,11 +24,9 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
private string _extendedAccountPrivateKey;
private string _extendedAccountZprv;
private string _warningMessage;
- private CompositeDisposable Disposables { get; }
public WalletInfoViewModel(WalletViewModel walletViewModel) : base(walletViewModel.Name, walletViewModel)
{
- Disposables = new CompositeDisposable();
ClearSensitiveData(true);
_warningMessage = "";
Closing = new CancellationTokenSource().DisposeWith(Disposables);
@@ -202,30 +200,21 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
#region IDisposable Support
- private volatile bool _disposedValue = false; // To detect redundant calls
-
- protected virtual void Dispose(bool disposing)
+ protected override void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
Closing?.Cancel();
- ClearSensitiveData(true);
- Disposables?.Dispose();
}
+ base.Dispose(disposing);
+
_disposedValue = true;
}
}
- // This code added to correctly implement the disposable pattern.
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
- Dispose(true);
- }
-
#endregion IDisposable Support
}
}

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/WalletViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/WalletViewModel.cs
@@ -3,6 +3,7 @@ using System.Collections.ObjectModel;
using System.Composition;
using System.IO;
using System.Linq;
+using System.Reactive.Disposables;
using System.Reactive.Linq;
using AvalonStudio.Extensibility;
using AvalonStudio.Shell;
@@ -14,8 +15,10 @@ using WalletWasabi.Services;
namespace WalletWasabi.Gui.Controls.WalletExplorer
{
- public class WalletViewModel : WasabiDocumentTabViewModel
+ public class WalletViewModel : WasabiDocumentTabViewModel, IDisposable
{
+ private CompositeDisposable Disposables { get; }
+
private ObservableCollection<WalletActionViewModel> _actions;
private string _title;
@@ -23,6 +26,8 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
public WalletViewModel(WalletService walletService, bool receiveDominant)
: base(Path.GetFileNameWithoutExtension(walletService.KeyManager.FilePath))
{
+ Disposables = new CompositeDisposable();
+
WalletService = walletService;
Name = Path.GetFileNameWithoutExtension(WalletService.KeyManager.FilePath);
var coinsChanged = Observable.FromEventPattern(Global.WalletService.Coins, nameof(Global.WalletService.Coins.CollectionChanged));
@@ -34,17 +39,17 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
.Subscribe(o =>
{
SetBalance(Name);
- });
+ }).DisposeWith(Disposables);
SetBalance(Name);
Actions = new ObservableCollection<WalletActionViewModel>
{
- new SendTabViewModel(this),
- new ReceiveTabViewModel(this),
- new CoinJoinTabViewModel(this),
- new HistoryTabViewModel(this),
- new WalletInfoViewModel(this)
+ new SendTabViewModel(this).DisposeWith(Disposables),
+ new ReceiveTabViewModel(this).DisposeWith(Disposables),
+ new CoinJoinTabViewModel(this).DisposeWith(Disposables),
+ new HistoryTabViewModel(this).DisposeWith(Disposables),
+ new WalletInfoViewModel(this).DisposeWith(Disposables)
};
Actions[0].DisplayActionTab();
@@ -83,5 +88,31 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
Money balance = Enumerable.Where(WalletService.Coins, c => c.Unspent).Sum(c => (long?)c.Amount) ?? 0;
Title = $"{walletName} ({balance.ToString(false, true)} BTC)";
}
+
+ #region IDisposable Support
+
+ private volatile bool _disposedValue = false; // To detect redundant calls
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposedValue)
+ {
+ if (disposing)
+ {
+ Disposables?.Dispose();
+ }
+
+ _disposedValue = true;
+ }
+ }
+
+ // This code added to correctly implement the disposable pattern.
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(true);
+ }
+
+ #endregion IDisposable Support
}
}

MODIFY
WalletWasabi.Gui/ViewModels/ViewModelBase.cs
WalletWasabi.Gui/ViewModels/ViewModelBase.cs
@@ -12,10 +12,7 @@ namespace WalletWasabi.Gui.ViewModels
{
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
- public bool HasErrors
- {
- get { return Validator.ValidateAllProperties(this).Any(); }
- }
+ public bool HasErrors => Validator.ValidateAllProperties(this).Any();
public IEnumerable GetErrors(string propertyName)
{

Dispose everything in Controls