88using System . Linq ;
99using Windows . Foundation ;
1010using Windows . Foundation . Collections ;
11- using WinUI . TableView . Helpers ;
11+ using WinUI . TableView . Extensions ;
1212
1313namespace WinUI . TableView ;
1414
@@ -17,19 +17,19 @@ namespace WinUI.TableView;
1717/// </summary>
1818internal partial class CollectionView : ICollectionView , ISupportIncrementalLoading , INotifyPropertyChanged , IComparer < object ? >
1919{
20- private IList _source = default ! ;
20+ 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.
2122 private bool _allowLiveShaping ;
2223 private readonly List < object ? > _view = [ ] ;
2324 private readonly ObservableCollection < FilterDescription > _filterDescriptions = [ ] ;
2425 private readonly ObservableCollection < SortDescription > _sortDescriptions = [ ] ;
25- private CollectionChangedListener < CollectionView > ? _collectionChangedListener ;
2626
2727 /// <summary>
2828 /// Initializes a new instance of the <see cref="CollectionView"/> class.
2929 /// </summary>
3030 /// <param name="source">The source collection.</param>
3131 /// <param name="liveShapingEnabled">Indicates whether live shaping is enabled.</param>
32- public CollectionView ( IList ? source = null , bool liveShapingEnabled = true )
32+ public CollectionView ( IEnumerable ? source = null , bool liveShapingEnabled = true )
3333 {
3434 _filterDescriptions . CollectionChanged += OnFilterDescriptionsCollectionChanged ;
3535 _sortDescriptions . CollectionChanged += OnSortDescriptionsCollectionChanged ;
@@ -64,6 +64,36 @@ private void OnSortDescriptionsCollectionChanged(object? sender, NotifyCollectio
6464 HandleSortChanged ( ) ;
6565 }
6666
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+
6797 /// <summary>
6898 /// Attaches property changed handlers to the items in the collection.
6999 /// </summary>
@@ -92,6 +122,75 @@ private void DetachPropertyChangedHandlers(IEnumerable? items)
92122 }
93123 }
94124
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+
95194 /// <summary>
96195 /// Handles changes to the source collection.
97196 /// </summary>
@@ -137,6 +236,9 @@ private void OnSourceCollectionChanged(object? arg1, NotifyCollectionChangedEven
137236 HandleSourceChanged ( ) ;
138237 }
139238
239+ DetachPropertyChangedHandlers ( e . OldItems ) ;
240+ AttachPropertyChangedHandlers ( _source ) ;
241+
140242 break ;
141243 }
142244 }
@@ -242,7 +344,7 @@ private void HandleSourceChanged()
242344 /// </summary>
243345 private void HandleFilterChanged ( )
244346 {
245- if ( FilterDescriptions . Any ( ) )
347+ if ( FilterDescriptions . Count > 0 )
246348 {
247349 for ( var index = 0 ; index < _view . Count ; index ++ )
248350 {
@@ -259,19 +361,21 @@ private void HandleFilterChanged()
259361
260362 var viewHash = new HashSet < object ? > ( _view ) ;
261363 var viewIndex = 0 ;
262- for ( var index = 0 ; index < _source . Count ; index ++ )
364+ var i = 0 ;
365+ foreach ( var item in _source )
263366 {
264- var item = _source [ index ] ! ;
265367 if ( viewHash . Contains ( item ) )
266368 {
267369 viewIndex ++ ;
268370 continue ;
269371 }
270372
271- if ( HandleItemAdded ( index , item , viewIndex ) )
373+ if ( HandleItemAdded ( i , item , viewIndex ) )
272374 {
273375 viewIndex ++ ;
274376 }
377+
378+ i ++ ;
275379 }
276380 }
277381
0 commit comments