@@ -12,8 +12,6 @@ namespace Catel.Collections
1212 using System . Collections . ObjectModel ;
1313 using System . Collections . Specialized ;
1414 using System . ComponentModel ;
15- using System . Diagnostics ;
16-
1715 using Catel . Logging ;
1816
1917 using IoC ;
@@ -47,6 +45,9 @@ public class FastObservableCollection<T> : ObservableCollection<T>, ISuspendChan
4745 [ field: NonSerialized ]
4846#endif
4947 private SuspensionContext < T > _suspensionContext ;
48+
49+ private readonly Stack < CollectionChangeEventArgs > _collectionEventArgs = new Stack < CollectionChangeEventArgs > ( ) ;
50+
5051 #endregion
5152
5253 #region Constructors
@@ -427,36 +428,33 @@ protected void NotifyChanges()
427428 {
428429 Action action = ( ) =>
429430 {
430- // Create event args
431- NotifyCollectionChangedEventArgs eventArgs = null ;
432- if ( _suspensionContext != null && _suspensionContext . Mode == SuspensionMode . Adding )
431+ List < NotifyCollectionChangedEventArgs > eventArgsList = new List < NotifyCollectionChangedEventArgs > ( ) ;
432+
433+ var suspensionContext = _suspensionContext ;
434+ if ( suspensionContext != null )
433435 {
434- if ( _suspensionContext . NewItems . Count != 0 )
436+ if ( suspensionContext . NewItems . Count != 0 )
435437 {
436- eventArgs = CreateEventArgs ( NotifyCollectionChangedAction . Add , _suspensionContext . NewItems , _suspensionContext . NewItemIndices ) ;
438+ eventArgsList . Add ( CreateEventArgs ( NotifyCollectionChangedAction . Add , suspensionContext . NewItems , suspensionContext . NewItemIndices ) ) ;
437439 }
438- }
439- else if ( _suspensionContext != null && _suspensionContext . Mode == SuspensionMode . Removing )
440- {
441- if ( _suspensionContext . OldItems . Count != 0 )
440+
441+ if ( suspensionContext . OldItems . Count != 0 )
442442 {
443- eventArgs = CreateEventArgs ( NotifyCollectionChangedAction . Remove , _suspensionContext . OldItems , _suspensionContext . OldItemIndices ) ;
443+ eventArgsList . Add ( CreateEventArgs ( NotifyCollectionChangedAction . Remove , suspensionContext . OldItems , suspensionContext . OldItemIndices ) ) ;
444444 }
445445 }
446446 else
447447 {
448- //Debug.Assert(_suspensionContext != null && _suspensionContext.Mode == SuspensionMode.None, "Wrong/unknown suspension mode!");
449-
450- eventArgs = CreateEventArgs ( NotifyCollectionChangedAction . Reset ) ;
448+ eventArgsList . Add ( CreateEventArgs ( NotifyCollectionChangedAction . Reset ) ) ;
451449 }
452450
453- // Fire events
454- if ( eventArgs != null )
451+ foreach ( var eventArgs in eventArgsList )
455452 {
456- OnPropertyChanged ( new PropertyChangedEventArgs ( "Count" ) ) ;
457- OnPropertyChanged ( new PropertyChangedEventArgs ( "Item[]" ) ) ;
458453 OnCollectionChanged ( eventArgs ) ;
459454 }
455+
456+ OnPropertyChanged ( new PropertyChangedEventArgs ( "Count" ) ) ;
457+ OnPropertyChanged ( new PropertyChangedEventArgs ( "Item[]" ) ) ;
460458 } ;
461459
462460 if ( AutomaticallyDispatchChangeNotifications )
@@ -475,7 +473,8 @@ protected void NotifyChanges()
475473 /// <param name="e">The <see cref="NotifyCollectionChangedEventArgs" /> instance containing the event data.</param>
476474 protected override void OnCollectionChanged ( NotifyCollectionChangedEventArgs e )
477475 {
478- if ( _suspensionContext == null || ( _suspensionContext != null && _suspensionContext . Count == 0 ) )
476+ var suspensionContext = _suspensionContext ;
477+ if ( suspensionContext == null || suspensionContext . Count == 0 )
479478 {
480479 if ( AutomaticallyDispatchChangeNotifications )
481480 {
@@ -489,7 +488,7 @@ protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
489488 return ;
490489 }
491490
492- if ( _suspensionContext != null && _suspensionContext . Count != 0 )
491+ if ( suspensionContext . Count != 0 )
493492 {
494493 IsDirty = true ;
495494 }
@@ -501,7 +500,8 @@ protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
501500 /// <param name="e">The <see cref="PropertyChangedEventArgs" /> instance containing the event data.</param>
502501 protected override void OnPropertyChanged ( PropertyChangedEventArgs e )
503502 {
504- if ( _suspensionContext == null || ( _suspensionContext != null && _suspensionContext . Count == 0 ) )
503+ var suspensionContext = _suspensionContext ;
504+ if ( suspensionContext == null || suspensionContext . Count == 0 )
505505 {
506506 if ( AutomaticallyDispatchChangeNotifications )
507507 {
@@ -521,13 +521,24 @@ protected override void OnPropertyChanged(PropertyChangedEventArgs e)
521521 protected override void ClearItems ( )
522522 {
523523 // Check
524- if ( _suspensionContext != null && _suspensionContext . Mode != SuspensionMode . None )
524+ var suspensionContext = _suspensionContext ;
525+ if ( suspensionContext != null && suspensionContext . Mode != SuspensionMode . None )
525526 {
526- throw Log . ErrorAndCreateException < InvalidOperationException > ( $ "Clearing items is only allowed in SuspensionMode.None, current mode is '{ _suspensionContext . Mode } '") ;
527+ throw Log . ErrorAndCreateException < InvalidOperationException > ( $ "Clearing items is only allowed in SuspensionMode.None, current mode is '{ suspensionContext . Mode } '") ;
527528 }
528529
529- // Call base
530- base . ClearItems ( ) ;
530+ if ( _suspensionContext != null && _suspensionContext . Mode == SuspensionMode . None )
531+ {
532+ while ( Count > 0 )
533+ {
534+ RemoveItem ( 0 ) ;
535+ }
536+ }
537+ else
538+ {
539+ // Call base
540+ base . ClearItems ( ) ;
541+ }
531542 }
532543
533544 /// <summary>
@@ -537,19 +548,22 @@ protected override void ClearItems()
537548 protected override void InsertItem ( int index , T item )
538549 {
539550 // Check
540- if ( _suspensionContext != null && _suspensionContext . Mode == SuspensionMode . Removing )
551+ var suspensionContext = _suspensionContext ;
552+ if ( suspensionContext != null && suspensionContext . Mode == SuspensionMode . Removing )
541553 {
542554 throw Log . ErrorAndCreateException < InvalidOperationException > ( "Adding items is not allowed in mode SuspensionMode.Removing." ) ;
543555 }
544556
557+ bool ? removed = suspensionContext ? . TryRemoveItemFromOldItems ( index , item ) ;
558+
545559 // Call base
546560 base . InsertItem ( index , item ) ;
547561
548- if ( _suspensionContext != null && _suspensionContext . Mode == SuspensionMode . Adding )
562+ if ( removed != null && ! removed . Value )
549563 {
550564 // Remember
551- _suspensionContext . NewItems . Add ( item ) ;
552- _suspensionContext . NewItemIndices . Add ( index ) ;
565+ suspensionContext . NewItems . Add ( item ) ;
566+ suspensionContext . NewItemIndices . Add ( index ) ;
553567 }
554568 }
555569
@@ -576,22 +590,25 @@ protected override void MoveItem(int oldIndex, int newIndex)
576590 protected override void RemoveItem ( int index )
577591 {
578592 // Check
579- if ( _suspensionContext != null && _suspensionContext . Mode == SuspensionMode . Adding )
593+ var suspensionContext = _suspensionContext ;
594+ if ( suspensionContext != null && suspensionContext . Mode == SuspensionMode . Adding )
580595 {
581596 throw Log . ErrorAndCreateException < InvalidOperationException > ( "Removing items is not allowed in mode SuspensionMode.Adding." ) ;
582597 }
583598
584599 // Get item
585600 T item = this [ index ] ;
586601
602+ bool ? removed = suspensionContext ? . TryRemoveItemFromNewItems ( index , item ) ;
603+
587604 // Call base
588605 base . RemoveItem ( index ) ;
589606
590- if ( _suspensionContext != null && _suspensionContext . Mode == SuspensionMode . Removing )
607+ if ( removed != null && ! removed . Value )
591608 {
592609 // Remember
593- _suspensionContext . OldItems . Add ( item ) ;
594- _suspensionContext . OldItemIndices . Add ( index ) ;
610+ suspensionContext . OldItems . Add ( item ) ;
611+ suspensionContext . OldItemIndices . Add ( index ) ;
595612 }
596613 }
597614
@@ -610,6 +627,7 @@ protected override void SetItem(int index, T item)
610627 // Call base
611628 base . SetItem ( index , item ) ;
612629 }
630+
613631 #endregion Overrides of ObservableCollection
614632
615633 private NotifyRangedCollectionChangedEventArgs CreateEventArgs ( NotifyCollectionChangedAction action , IList changedItems = null , IList < int > changedIndices = null )
0 commit comments