Skip to content

Commit d6bb2ff

Browse files
committed
add ICollectionView changes handling
1 parent 2ff6378 commit d6bb2ff

2 files changed

Lines changed: 108 additions & 10 deletions

File tree

src/ItemsSource/CollectionView.Properties.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using Microsoft.UI.Xaml.Data;
22
using System.Collections;
33
using System.Collections.Generic;
4-
using System.Collections.Specialized;
54
using Windows.Foundation.Collections;
65
using WinUI.TableView.Extensions;
76

@@ -19,17 +18,15 @@ public IEnumerable Source
1918
{
2019
if (_source == value) return;
2120

22-
if (_source is not null) DetachPropertyChangedHandlers(_source);
21+
DetachCollectionChangedHandlers(_source);
22+
DetachPropertyChangedHandlers(_source);
2323

2424
_source = value;
25-
AttachPropertyChangedHandlers(_source);
2625

27-
_collectionChangedListener?.Detach();
26+
AttachCollectionChangedHandlers(_source);
27+
AttachPropertyChangedHandlers(_source);
2828

29-
if (_source is INotifyCollectionChanged sourceNcc)
30-
{
31-
_collectionChangedListener = new(this, sourceNcc, OnSourceCollectionChanged);
32-
}
29+
CreateItemsCopy(_source);
3330

3431
HandleSourceChanged();
3532
OnPropertyChanged();

src/ItemsSource/CollectionView.cs

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
using Windows.Foundation;
1010
using Windows.Foundation.Collections;
1111
using WinUI.TableView.Extensions;
12-
using WinUI.TableView.Helpers;
1312

1413
namespace WinUI.TableView;
1514

@@ -19,11 +18,11 @@ namespace WinUI.TableView;
1918
internal partial class CollectionView : ICollectionView, ISupportIncrementalLoading, INotifyPropertyChanged, IComparer<object?>
2019
{
2120
private IEnumerable _source = new List<object>();
21+
private object[] _itemsCopy = []; // In case the source is ICollection, keep a copy of the items to keep track of removed items.
2222
private bool _allowLiveShaping;
2323
private readonly List<object?> _view = [];
2424
private readonly ObservableCollection<FilterDescription> _filterDescriptions = [];
2525
private readonly ObservableCollection<SortDescription> _sortDescriptions = [];
26-
private CollectionChangedListener<CollectionView>? _collectionChangedListener;
2726

2827
/// <summary>
2928
/// Initializes a new instance of the <see cref="CollectionView"/> class.
@@ -65,6 +64,36 @@ private void OnSortDescriptionsCollectionChanged(object? sender, NotifyCollectio
6564
HandleSortChanged();
6665
}
6766

67+
/// <summary>
68+
/// Attaches collection changed handlers to the source collection.
69+
/// </summary>
70+
private void AttachCollectionChangedHandlers(IEnumerable source)
71+
{
72+
if (source is INotifyCollectionChanged sourceNcc)
73+
{
74+
sourceNcc.CollectionChanged += OnSourceCollectionChanged;
75+
}
76+
else if (source is ICollectionView sourceCV)
77+
{
78+
sourceCV.VectorChanged += OnSourceVectorChanged;
79+
}
80+
}
81+
82+
/// <summary>
83+
/// Detaches collection changed handlers from the source collection.
84+
/// </summary>
85+
private void DetachCollectionChangedHandlers(IEnumerable source)
86+
{
87+
if (source is INotifyCollectionChanged sourceNcc)
88+
{
89+
sourceNcc.CollectionChanged -= OnSourceCollectionChanged;
90+
}
91+
else if (source is ICollectionView sourceCV)
92+
{
93+
sourceCV.VectorChanged -= OnSourceVectorChanged;
94+
}
95+
}
96+
6897
/// <summary>
6998
/// Attaches property changed handlers to the items in the collection.
7099
/// </summary>
@@ -93,6 +122,75 @@ private void DetachPropertyChangedHandlers(IEnumerable? items)
93122
}
94123
}
95124

125+
/// <summary>
126+
/// Handles changes to the source vector.
127+
/// </summary>
128+
private void OnSourceVectorChanged(IObservableVector<object> sender, IVectorChangedEventArgs args)
129+
{
130+
var index = (int)args.Index;
131+
132+
switch (args.CollectionChange)
133+
{
134+
case CollectionChange.ItemInserted:
135+
if (_deferCounter <= 0)
136+
{
137+
if (index < Count)
138+
{
139+
var item = sender[index];
140+
AttachPropertyChangedHandlers(new object[] { item });
141+
HandleItemAdded(index, item);
142+
}
143+
else
144+
{
145+
HandleSourceChanged();
146+
}
147+
}
148+
149+
break;
150+
case CollectionChange.ItemRemoved:
151+
if (_deferCounter <= 0)
152+
{
153+
if (index < _itemsCopy.Length)
154+
{
155+
var item = _itemsCopy[index];
156+
DetachPropertyChangedHandlers(new object[] { item });
157+
HandleItemRemoved(index, item);
158+
}
159+
else
160+
{
161+
HandleSourceChanged();
162+
}
163+
}
164+
165+
break;
166+
case CollectionChange.ItemChanged:
167+
case CollectionChange.Reset:
168+
if (_deferCounter <= 0)
169+
{
170+
HandleSourceChanged();
171+
}
172+
173+
DetachPropertyChangedHandlers(_itemsCopy);
174+
AttachPropertyChangedHandlers(_source);
175+
176+
break;
177+
}
178+
179+
CreateItemsCopy(_source);
180+
}
181+
182+
/// <summary>
183+
/// Creates a copy of the items from the collection if it implements ICollectionView.
184+
/// </summary>
185+
private void CreateItemsCopy(IEnumerable source)
186+
{
187+
if (source is ICollectionView collectionView)
188+
{
189+
_itemsCopy = new object[collectionView.Count];
190+
collectionView.CopyTo(_itemsCopy, 0);
191+
}
192+
}
193+
96194
/// <summary>
97195
/// Handles changes to the source collection.
98196
/// </summary>
@@ -138,6 +236,9 @@ private void OnSourceCollectionChanged(object? arg1, NotifyCollectionChangedEven
138236
HandleSourceChanged();
139237
}
140238

239+
DetachPropertyChangedHandlers(e.OldItems);
240+
AttachPropertyChangedHandlers(_source);
241+
141242
break;
142243
}
143244
}

0 commit comments

Comments
 (0)