fix memory issues with coinlistviewmodel and polish code.
MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/CoinListViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/CoinListViewModel.cs
@@ -183,20 +183,24 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
public CoinListViewModel()
{
RemovedCoinViewModels = new List<CoinViewModel>();
- AmountSortDirection = SortOrder.Decreasing;
- RefreshOrdering();
var sortChanged = this.WhenValueChanged(@this => MyComparer).Select(_ => MyComparer);
RootList = new SourceList<CoinViewModel>();
RootList.Connect()
- .OnItemAdded(cvm => cvm.PropertyChanged += Coin_PropertyChanged)
- .OnItemRemoved(cvm => RemovedCoinViewModels.Add(cvm)) //TODO: fix and test. If I directly unsubscribe from Coin_PropertyChanged then Unspent propchange not triggered in some cases => spent money stays in list
+ .OnItemRemoved(x=>x.UnsubscribeEvents())
.Sort(MyComparer, comparerChanged: sortChanged, resetThreshold: 5)
.Bind(out _coinViewModels)
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe();
+ SortCommand = ReactiveCommand.Create(() => RefreshOrdering());
+
+ AmountSortDirection = SortOrder.Decreasing;
+ RefreshOrdering();
+
+ RootList = new SourceList<CoinViewModel>();
+
this.WhenAnyValue(x => x.AmountSortDirection).Subscribe(x =>
{
if (x != SortOrder.None)
@@ -306,50 +310,6 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
break;
}
});
-
- SortCommand = ReactiveCommand.Create(() => RefreshOrdering());
-
- RemovedCoinViewModels = new List<CoinViewModel>();
-
- this.WhenAnyValue(x => x.AmountSortDirection).Subscribe(x =>
- {
- if (x != SortOrder.None)
- {
- PrivacySortDirection = SortOrder.None;
- StatusSortDirection = SortOrder.None;
- }
- });
-
- this.WhenAnyValue(x => x.StatusSortDirection).Subscribe(x =>
- {
- if (x != SortOrder.None)
- {
- AmountSortDirection = SortOrder.None;
- PrivacySortDirection = SortOrder.None;
- }
- });
-
- this.WhenAnyValue(x => x.PrivacySortDirection).Subscribe(x =>
- {
- if (x != SortOrder.None)
- {
- AmountSortDirection = SortOrder.None;
- StatusSortDirection = SortOrder.None;
- }
- });
-
-
- AmountSortDirection = SortOrder.Decreasing;
- RefreshOrdering();
-
- RootList = new SourceList<CoinViewModel>();
- RootList.Connect()
- .OnItemAdded(cvm => cvm.PropertyChanged += Coin_PropertyChanged)
- .OnItemRemoved(cvm => cvm.PropertyChanged -= Coin_PropertyChanged) //TODO: fix and test. If I directly unsubscribe from Coin_PropertyChanged then Unspent propchange not triggered in some cases => spent money stays in list
- .Sort(MyComparer, comparerChanged: sortChanged, resetThreshold: 5)
- .Bind(out _coinViewModels)
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe();
}
public void OnOpen()
@@ -358,59 +318,22 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
foreach (var sc in Global.WalletService.Coins.Where(sc => sc.Unspent))
{
- RootList.Add(new CoinViewModel(sc).DisposeWith(_disposables));
+ RootList.Add(new CoinViewModel(this, sc));
}
- Global.WalletService.Coins.CollectionChanged += Coins_CollectionGlobalChanged;
-
-
- SetSelections();
- SetCoinJoinStatusWidth();
- }
-
- public void OnClose()
- {
- if (Global.WalletService?.Coins != null)
- {
- Global.WalletService.Coins.CollectionChanged -= Coins_CollectionGlobalChanged;
- }
-
- if (RootList?.Items != null)
- {
- foreach (CoinViewModel cvm in RootList.Items)
- {
- if (cvm != null)
- {
- cvm.PropertyChanged -= Coin_PropertyChanged;
- }
- }
- }
-
- if (RemovedCoinViewModels != null)
- {
- foreach (var cvm in RemovedCoinViewModels)
- {
- if (cvm != null)
- {
- cvm.PropertyChanged -= Coin_PropertyChanged;
- }
- }
- }
-
- RootList.Clear();
- _disposables?.Dispose();
- }
-
- private void Coins_CollectionGlobalChanged(object sender, NotifyCollectionChangedEventArgs e)
+ Observable.FromEventPattern<NotifyCollectionChangedEventArgs>(Global.WalletService.Coins, nameof(Global.WalletService.Coins.CollectionChanged))
+ .ObserveOn(RxApp.MainThreadScheduler)
+ .Subscribe(x =>
{
- Dispatcher.UIThread.PostLogException(() =>
+ var e = x.EventArgs;
+ try
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (SmartCoin c in e.NewItems.Cast<SmartCoin>().Where(sc => sc.Unspent && !sc.IsDust))
{
- RootList.Add(new CoinViewModel(c));
+ RootList.Add(new CoinViewModel(this, c));
}
break;
@@ -426,10 +349,36 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
break;
case NotifyCollectionChangedAction.Reset:
- RootList.Clear();
+ ClearRootList();
break;
}
- });
+ }
+ catch (Exception ex)
+ {
+ Logging.Logger.LogDebug<Dispatcher>(ex);
+ }
+ }).DisposeWith(_disposables);
+
+
+ SetSelections();
+ SetCoinJoinStatusWidth();
+ }
+
+ private void ClearRootList()
+ {
+ foreach (var item in RootList.Items)
+ {
+ item.UnsubscribeEvents();
+ }
+
+ RootList.Clear();
+ }
+
+ public void OnClose()
+ {
+ ClearRootList();
+
+ _disposables?.Dispose();
}
private void SetSelections()
@@ -457,23 +406,19 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
}
}
- private void Coin_PropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- Dispatcher.UIThread.PostLogException(() =>
- {
- if (e.PropertyName == nameof(CoinViewModel.IsSelected))
+ public void OnCoinIsSelectedChanged(CoinViewModel cvm)
{
SetSelections();
- var cvm = sender as CoinViewModel;
SelectionChanged?.Invoke(this, cvm);
}
- if (e.PropertyName == nameof(CoinViewModel.Status))
+
+ public void OnCoinStatusChanged()
{
SetCoinJoinStatusWidth();
}
- if (e.PropertyName == nameof(CoinViewModel.Unspent))
+
+ public void OnCoinUnspentChanged(CoinViewModel cvm)
{
- var cvm = (CoinViewModel)sender;
if (!cvm.Unspent)
{
RootList.Remove(cvm);
@@ -482,7 +427,5 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
SetSelections();
SetCoinJoinStatusWidth();
}
- });
- }
}
}

fix memory issues with coinlistviewmodel and polish code.