From 0050439932a9c89a6c87352f27568c0c460419e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= Date: Tue, 5 Sep 2023 11:11:15 +0200 Subject: [PATCH] Fix ItemsControl not handling collection changed --- .../TerminalUI/Controls/ItemsControl.cs | 21 +++++++++++++++++-- src/Library/TerminalUI/Controls/ListView.cs | 15 +++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/Library/TerminalUI/Controls/ItemsControl.cs b/src/Library/TerminalUI/Controls/ItemsControl.cs index 71039fa..d9e50b8 100644 --- a/src/Library/TerminalUI/Controls/ItemsControl.cs +++ b/src/Library/TerminalUI/Controls/ItemsControl.cs @@ -1,4 +1,5 @@ using System.Collections.ObjectModel; +using System.Collections.Specialized; using ObservableComputations; using PropertyChanged.SourceGenerator; using TerminalUI.Models; @@ -27,6 +28,10 @@ public sealed partial class ItemsControl set { if (_itemsSource == value) return; + + if(_itemsSource is INotifyCollectionChanged notifyCollectionChanged) + notifyCollectionChanged.CollectionChanged -= SourceCollectionChanged; + _itemsSource = value; foreach (var disposable in _itemsDisposables) @@ -39,17 +44,25 @@ public sealed partial class ItemsControl if (_itemsSource is ObservableCollection observableDeclarative) { var consumer = new OcConsumer(); - _children = observableDeclarative + var children = observableDeclarative .Selecting(i => CreateItem(i)) .For(consumer); + + children.CollectionChanged += SourceCollectionChanged; + _children = children; + _itemsDisposables.Add(consumer); } else if (_itemsSource is ReadOnlyObservableCollection readOnlyObservableDeclarative) { var consumer = new OcConsumer(); - _children = readOnlyObservableDeclarative + var children = readOnlyObservableDeclarative .Selecting(i => CreateItem(i)) .For(consumer); + + children.CollectionChanged += SourceCollectionChanged; + _children = children; + _itemsDisposables.Add(consumer); } else if (_itemsSource is ICollection collection) @@ -78,6 +91,10 @@ public sealed partial class ItemsControl RerenderProperties.Add(nameof(Orientation)); } + private void SourceCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) => RequestRerenderForThis(); + + private void RequestRerenderForThis() + => ApplicationContext?.RenderEngine.RequestRerender(this); protected override Size CalculateSize() { diff --git a/src/Library/TerminalUI/Controls/ListView.cs b/src/Library/TerminalUI/Controls/ListView.cs index 19a8fae..7916f30 100644 --- a/src/Library/TerminalUI/Controls/ListView.cs +++ b/src/Library/TerminalUI/Controls/ListView.cs @@ -76,6 +76,10 @@ public sealed partial class ListView : View : View observableDeclarative) { - ((INotifyCollectionChanged) observableDeclarative).CollectionChanged += - (_, _) => ApplicationContext?.RenderEngine.RequestRerender(this); + ((INotifyCollectionChanged) observableDeclarative).CollectionChanged += SourceCollectionChanged; _getItems = () => observableDeclarative; } else if (_itemsSource is ReadOnlyObservableCollection readOnlyObservableDeclarative) { - ((INotifyCollectionChanged) readOnlyObservableDeclarative).CollectionChanged += - (_, _) => ApplicationContext?.RenderEngine.RequestRerender(this); + ((INotifyCollectionChanged) readOnlyObservableDeclarative).CollectionChanged += SourceCollectionChanged; _getItems = () => readOnlyObservableDeclarative; } @@ -135,6 +137,11 @@ public sealed partial class ListView : View RequestRerenderForThis(); + + private void RequestRerenderForThis() + => ApplicationContext?.RenderEngine.RequestRerender(this); + protected override Size CalculateSize() { InstantiateItemViews();