void HandleSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { // Firstly if we are copying the source collection into our filtered list, update // the copy with the new changes and compute the actual index of our item in the // sorted/grouped/filtered list. int actualOldIndex = -1; int actualNewIndex = -1; bool originalList = ActiveList == SourceCollection; if (!originalList) { switch (e.Action) { case NotifyCollectionChangedAction.Add: foreach (object o in e.NewItems) { AddToFilteredAndGroupSorted(o); } break; case NotifyCollectionChangedAction.Remove: actualOldIndex = IndexOf(e.OldItems [0]); foreach (object o in e.OldItems) { RemoveFromFilteredAndGroup(o); } break; case NotifyCollectionChangedAction.Replace: foreach (object o in e.OldItems) { RemoveFromFilteredAndGroup(o); } foreach (object o in e.NewItems) { AddToFilteredAndGroupSorted(o); } break; case NotifyCollectionChangedAction.Reset: filteredList.Clear(); RootGroup.ClearSubtree(); foreach (var o in SourceCollection) { AddToFilteredAndGroup(o); } break; } } else { // Raise the collection changed event RaiseCollectionChanged(e); } IsEmpty = ActiveList.Count == 0; IsCurrentAfterLast = CurrentPosition == ActiveList.Count || ActiveList.Count == 0; IsCurrentBeforeFirst = CurrentPosition == -1 || ActiveList.Count == 0; }