public void RecalculateFilter() { if (Filter == null) { FilteredItems.ForEach(item => InternalAdd(item)); FilteredItems.Clear(); } else { // Remove the items that no longer pass the filter var itemsRemovedByNewFilter = new List <T>(); for (int i = BackingList.Count - 1; i >= 0; i--) { if (!PassesFilter(BackingList[i])) { itemsRemovedByNewFilter.Add(BackingList[i]); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, BackingList[i], i)); base.RemoveAt(i); } } // Add the previously filtered items that that now pass FilteredItems.RemoveWhere(item => { var insertionIndex = InternalAdd(item); if (insertionIndex >= 0) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, insertionIndex)); return(true); } return(false); }); // Don't move items into the filtered list until it has been iterated over FilteredItems.UnionWith(itemsRemovedByNewFilter); } }